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)如果没有参数,必须使用一组空的圆括号。