委托

1 什么是委托
委托是持有一个或多个方法的对象,是一种可以执行的对象,执行时,就相当于执行其持有的方法,委托的本质就是一个类型安全的方法的指针。 
委托和类一样,是一种用户自定义的类型,而类表示的是数据和方法的集合,而委托则持有一个或多个方法,以及一系列预定义操作。
       delegatevoidMyDel(int x);//声明委托类型 
       classProgram
       {
            staticvoid PrintLow(int x)
            {
                Console.WriteLine("{0}--Low Value", x);
            }
            staticvoid PrintHigh(int x)
            {
                Console.WriteLine("{0}--High Value", x);
            }
            staticvoid Main()
            {
                MyDel del;//声明委托变量
                Random rand = newRandom();
                int randValue = rand.Next(99);
                del = randValue < 50 ? newMyDel(PrintLow) : newMyDel(PrintHigh);//创建一个包含PrintLow或PrintHigh方法的委托对象,并将其值赋给del变量
                del(randValue);//执行委托
                Console.ReadLine();
            }
         }
以上就是一个委托使用的示例代码,代码开始部分先声明了一个委托类型MyDel,在main中声明了一个MyDel委托类型的变量,当对其初始化时,该变量就持有对应方法的引用。
2 委托概述
使用委托操作步骤:
(1)声明一个委托类型。
(2)使用该委托类型声明一个委托变量;
(3)创建委托类型的对象,把它赋值给委托变量,新的委托对象包括指向某个方法的引用。这个方法和第一步定义的签名和返回类型一致。
(4)可以选中为委托对象增加其他方法,这些方法必须与第一步中定义的委托类型有相同的签名和返回类型。
(5)在代码中可以像调用方法一样调用委托,在调用委托的时候,其包含的每一个方法都会被执行。
                                                     
委托调用的多个方法的列表叫做调用列表,调用列表的方法可以来自任何类或结构,只要返回类型和签名(包括ref和out修饰符)相同,这些方法可以是实例方法也可以是静态方法。
3 声明委托类型
                                        
委托类型声明看上去和方法的声明一样,但它不需要在类内部声明,因为它是类型声明。
与方法声明的不同:委托声明已delegate关键字开头;没有方法体。
4 创建委托对象
两种方式:
     del =new MyDel(PrintLow);
     del =PrintLow;//快捷语法
5 给委托赋值
委托是引用类型,被赋值后旧的委托对象会被垃圾回收器回收。上面的第一句del在第二句后会被回收。
6 组合委托

7 为委托添加方法
使用+=运算符  实执行add 方法:
                
由于委托是不可变的,所以使用+=运算符时,实际发生的是创建了一个新的委托,其调用列表时相加结果。
8 从委托移除方法
使用-=运算符,同上,移除时是从调用列表的最后开始搜素。实际执行Remove方法
9 调用委托
当委托调用列表有多个时,执行委托时传入的参数会在多个方法调用时都使用。例如上面的执行时,三个方法就是都是用55这个参数。
10 调用带返回值的委托
如果委托有返回值且调用列表多于一个,则返回调用列表最后一个方法返回的值,其他的都被忽略。
11调用带引用参数的委托
如果委托有引用参数(带ref),参数值在调用多个方法期间会发生改变。

执行结果是 12

12 匿名方法

使用匿名方法:(1)可以在声明委托变量时作为初始化表达式;(2)组合委托时在赋值语句的右边;(3)为委托增加事件时在赋值语句的右边。
匿名方法的语法:
                           

返回类型:匿名方法本身没有显示的声明返回值,所以在匿名方法的方法体内必须有和委托的返回一致的返回值。
参数:除数组参数外,匿名方法的参数列表必须在参数数量、类型、位置、参数修饰符方面与委托匹配。当委托参数列表不包含任何out参数,匿名方法本身也不需要使用任何参数时,可以省略参数列表。
params参数:
                     

13 变量和参数的作用域
外部变量

只要捕获方法还是委托的一部分,即使变量已经离开了作用域,捕获的外部变量也会一直有效。以上例子中mDel委托中的匿名方法在它的环境中保留了x,并在调用mDel时输出了它的值。
14 Lambda表达式
Lambda表达式是在C#3.0中引入的,是为了简化匿名方法而出现的,如果先有Lambda表达式就不会有匿名方法了。Lambda表达式运算符=>读作"goes to".以下例子显示了怎么一步步简化匿名方法得到Lambda表达式。这些写法都是正确的。
            MyDel del = delegate(int x)    { return x + 1; };
            MyDel le1 =         (int x) => { return x + 1; };
            MyDel le2 =             (x) => { return x + 1; };
            MyDel le3 =               x => { return x + 1; };
            MyDel le4 =               x => x + 1;

Lambda表达式的语法:
                                    
(1)左边的参数必须在数量、类型和位置上与委托相匹配;
(2)参数一般不需要写明类型,除非委托有ref、out参数时必须注明类型;
(3)只有一个参数,且类型是已知的(通过委托编译器可知晓),则括号可以省略,否则必须有括号;
(4)如果没有参数,必须使用一组空的圆括号。
原文地址:https://www.cnblogs.com/rwh871212/p/6963136.html