• 基础拾遗------委托、事件详解


    基础拾遗:

    基础拾遗------特性详解

    基础拾遗------webservice详解

    基础拾遗------redis详解

    基础拾遗------反射详解

    基础拾遗------委托、事件详解

    基础拾遗------接口详解

    基础拾遗------泛型详解

    基础拾遗-----依赖注入

    基础拾遗-----数据注解与验证

    基础拾遗-----mongoDB操作

    基础拾遗----RabbitMQ

    基础拾遗---CLR

    前言:

      C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。委托是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。委托(Delegate)特别用于实现事件和回调方法。所有的委托都派生自 System.Delegate 类。把一个方法当作参数传递,让其它方法进行调用执行。

    1.委托的声明

    委托声明决定了可由该委托引用的方法。委托可指向一个与其具有相同标签的方法。

    1.1.delegate

    1.1.1. 0-23个参数,可以有返回值也可以没有返回值

    public delegate int MyDelegateEventHandler (string parm);

    注:(1).此委托指向的方法必须是参数为string类型,返回类型为int类型的。其他声明类比所得。

      (2).EventHandler是c# 命名规范,当然我理解规范就是可以随意啦。

           (3).委托调用时必须判断是否为null不然会报异常

           (4).事件也是一种委托

    1.1.2.委托的调用

    MyDelegateEventHandler fun=new MyDelegateEventHandler(method);
    or
    MyDelegateEventHandler fun=method;
    // fun不为空,则调用回调方法
     if (fun!= null)
        {
             fun(val);
         }
     //fun?.Invoke(val); 简化版本调用 

    1.1.3.委托的多播

    每个委托都只包含一个方法调用,如果调用多个方法,就需要多次显示调用这个委托。如果同一个委托调用多个方法,我们就可以用多播委托

    public delegate void MyDelegate ();
    
    public voidMyMethod()
    {
        //#
    }
    public void MyMethod1()
    {
        //#
    }
    public void MyMethod2()
    {
        //#
    }
    MyDelegateEnventHander myDelegate;
    myDelegate=new MyDelegateEventHander(MyMethod);
    myDelegate+=new MyDelegateEventHander(MyMethod1);
    ...........
    //调用
    myDelegate();

     注:

      1.委托对象可使用 "+" 运算符进行合并;

      2."-" 运算符可用于从合并的委托中移除组件委托;

      3.委托指定方法类型必须一致;

      4.返回类型一般为void,但非必须;

      5.GetInvocationList获取委托索引

    if (MyDelegate != null) 
        System.Delegate[] dels = MyDelegate .GetInvocationList(); 
    for (int i = 0; i < dels.Length; i++) 
      {
          MyDelegate  -= dels[i] as MethodDelegate;
       }     

    以上是利用GetInvocationList获取委托索引的一个简单应用。

    1.2.Action

     Action至少0个参数,至多16个参数,无返回值。

    Action 表示无参,无返回值的委托
    Action<int,string> 表示有传入参数int,string无返回值的委托
    Action<int,string,bool> 表示有传入参数int,string,bool无返回值的委托
    Action<int,int,int,int> 表示有传入4个int型参数,无返回值的委托
    
     public void Test<T>(Action<T> action,T p)
            {
                action(p);
            }

    1.3.Func

     Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void

    Func是无返回值的泛型委托
    Func<int> 表示无参,返回值为int的委托
    Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
    Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
    Func<T1,T2,,T3,int> 表示传入参数为T1,T2,,T3(泛型)返回值为int的委托

    1.4.predicate

    1.4.1.predicate 是返回bool型的泛型委托;

    1.4.2.predicate<int> 表示传入参数为int 返回bool的委托;

    1.4.3.Predicate有且只有一个参数,返回值固定为bool;

    public delegate bool Predicate<T> (T obj)

    2.委托的实例化

    2.1.delegate

    public delegate int MyDelegateEventHandler (string parm)
    public int MyMethod(string parm)
    {
        //#
    }
    MyDelegateEventHandler MyDelegate=new MyDelegateEventHandler(MyMethod)

    注:委托实例化的时候,委托对象必须使用 new 关键字来创建,且与一个特定的方法有关。委托参数中的方法不含参数。

    2.2.Action的使用

     public void Test<T>(Action<T> action, T p)
      {
        action(p);
      }
     private void Action(string s)
     {
      #
     }
    //调用
    Test<string>(Action,"wyl");

    2.3.Func的使用

    public int Test<T1, T2>(Func<T1, T2, int> func, T1 a, T2 b)
    {
     return func(a, b);
    }
    private int Fun(int a, int b)
    {
      #
    }
    //调用
    Test<int,int>(Fun,100,200)

    2.4 委托实现冒泡排序

    //定义对象
    class Student
        {
            public string Name { get; private set; }
            public decimal Scores{ get; private set; }
    
            public Student(string name, decimal scores)
            {
                this.Name = name; this.Scores= scores;
            }
            public override string ToString()
            {
                return string.Format("{0},{1:C}",Name,Scores);
            }
            public static bool CompareScores(Student e1,Student e2)
            {
                return e1.Scores< e2.Scores;
            }
        }
    //利用委托实现冒泡
    class BubbleScores
        {
            public static void Sort<T>(IList<T> sortArray, Func<T, T, bool> comparison)
            {
                bool swapped = true;
                do
                {
                    swapped = false;
                    for (int i = 0; i < sortArray.Count - 1; i++)
                    {
                        if (comparison(sortArray[i + 1], sortArray[i]))
                        {
                            T temp = sortArray[i];
                            sortArray[i] = sortArray[i + 1];
                            sortArray[i + 1] = temp;
                            swapped = true;
                        }
                    }
                } while (swapped);
            }
        }
    //调用
    Student[] students={new Student("wyl", 100),#};
    BubbleSorter.Sort(students, Student.CompareScores);
    foreach(var student in students)
        Console.WriteLine(student);

    3.匿名函数与lambda 

    3.1什么是匿名函数

    匿名函数是一个“内联”语句或表达式,可在需要委托类型的任何地方使用。

    可以使用匿名函数来初始化命名委托(无需取名字的委托),或传递命名委托(而不是命名委托类型,传递一个方法块,而不是委托类型)[callback的方式]作为方法参数。

    MyDelegate funDelegate = delegate(string s) { Console.WriteLine(s); };
    funDelegate ("this is anonymous delegate");

    3.2.lambda

    lambda表达式实际上是一个匿名函数。编译器在看到lambda之后会在类中自动定义一个新的私有方法。lambda必须匹配委托!其中lambda是从c#3.0后引用的

    lambda的语法:

    参数 => 方法体。

    =>左边是要传入的参数,本例中是传入一个Int类型的变量,=>右边是具体的代码。

    //如果不传递参数:
    ()=>Console.WriteLine("Hello World!")
    //传递一个参数:
    (int n)=>Console.WriteLine(n.ToString())   
    //或者去掉()和int  编译器会自己推断类型:
    n=>Console.WriteLine(n.ToString())
    //传递多个参数:
    (int n ,int m)=>Console.WriteLine(n+m) 
    //或者编译器自己推断类型:
    (n , m)=>Console.WriteLine(m+n)

    4.事件

    4.1 什么是事件

    事件是以委托为基础也可以说就是一种委托,事件能实现的委托都能实现。他们的区别在于事件只能在方法内使用。

    /// <summary>  
    /// 声明委托  
    /// </summary>    
    public delegate void EventHander(string a);
    /// <summary>
    /// 声明委托相关的事件
    /// </summary>
    public event EventHander EventMain;

    4.2.猫和老鼠

    4.2.1猫的定义

    /// <summary>
    /// 猫类
    /// </summary>
        class Cat
        {
            public string Name { get; private set; }
            public string Color { get; private set; }
     
            public delegate void CatComeEventHandler();
            public event CatComeEventHandler CatComeEvent;//声明“猫来了”的事件
     
            public Cat(string name,string color)
            {
                this.Name = name;
                this.Color = color;
     
            }
     
            public void CatCome()
            {
                Console.WriteLine(Color+"的猫,名字叫:"+Name+",跑过来了。。。");
                CatComeEvent();//触发“猫来了”的事件
            }
    View Code

    4.2.2.老鼠的定义

        /// <summary>
        /// 老鼠类
        /// </summary>
        class Mouse
        {
            public string Name { get; private set; }
            public string Color { get; private set; }
     
            public Mouse(string name,string color,Cat cat)
            {
                this.Name = name;
                this.Color = color;
                cat.CatComeEvent += this.MouseRun;//订阅“猫来了”的事件,并做出反应,老鼠逃跑 MouseRun
            }
     
            public void MouseRun()
            {
                Console.WriteLine(Color + "" +Name+"老鼠,逃跑了");
            }
        }
    View Code

    4.2.3.猫来了老鼠跑

            static void Main(string[] args)
            {
                Cat Tom = new Cat("汤姆", "蓝色");
                Mouse Jerry = new Mouse("杰瑞", "灰色",Tom);
                Mouse Jack = new Mouse("杰克", "黑色",Tom);
                //Tom.CatComeEvent += new Cat.CatComeEventHandler(Jerry.MouseRun);
                //Tom.CatComeEvent+= new Cat.CatComeEventHandler(Jack.MouseRun);
                //Tom.CatComeEvent+= Jerry.MouseRun;
                //Tom.CatComeEvent += Jack.MouseRun;
     
                Tom.CatCome();
                Console.ReadKey();
            }
    View Code
  • 相关阅读:
    boltdb 学习和实践
    解读-m addrtype --dst-type LOCAL -j DOCKER
    找到linux中当前java的安装位置
    java.library.path是什么?
    Linux 中【./】和【/】和【.】之间有什么区别?
    [SpringMVC]JSON乱码问题
    iOS MVVM的理解与分析
    iOS中为什么必须在主线程操作UI
    几种直播流媒体协议
    IOS硬编码
  • 原文地址:https://www.cnblogs.com/wyl1924/p/5688939.html
Copyright © 2020-2023  润新知