深入理解C#(十二)
*第五章(C# 2:进入快速通道的委托(下))
匿名方法
使用匿名方法的内联委托操作
C# 1中的问题:用特定签名来实现委托是很常见的情况。有时只需要一个委托来做一件很简单的事,但是必须创建一个完整的新方法。
匿名方法允许指定一个内联委托实例的操作,作为创建委托实例表达式的一部分。
简单的匿名方法实例:处理一个参数
.NET 2.0有一个泛型委托类型Actionpublic delegate void Action<T>(T obj)
Action
实例:
1 | Action<string> printReverse = delegate (string text) |
匿名方法的语法:
delegate关键字,参数,代码块(定义对委托实例的操作)匿名方法的结果是一个委托实例,和调用普通方法一样调用委托。
1 | printReverse("hello world"); |
逆变性不适用于匿名方法:必须指定和委托类型完全匹配的参数类型
匿名方法的是实现,是在IL中为源代码中断每个匿名方法创建一个方法
一个更精简的极端例子:体现匿名方法的一般用法,即作为传给另一个方法的参数使用。
1 | List<int> x = new List<int>(); |
匿名方法的返回值
1 | Predicate<int> isEven = delegate (int x) |
没有必要再声明一个返回类型,因为编译器会检查是否所有可能返回值都兼容于委托类型声明的返回类型。
忽略委托参数
1 | class IgnoredParametersAnonymousMethods |
一般写法:button.Click+=delegate(object sender,EventArgs e){...}
匿名方法中的捕获变量
匿名方法外部对变量的更改在匿名方法内部是可见的,反之亦然。
1 | static void Main() |
创建委托实例不会导致执行
在整个方法中,我们使用的始终是同一个captured变量
捕获变量的实际用处
能简化避免专门创建一些类来存储一个委托需要处理的信息(除了作为参数传递信息之外)
1 | List<Person> FindAllYoungerThan(List<Person> people,int limit) |
我们在委托实例内部捕获了limit参数,若不支持捕获变量,就不能使用作为参数传递的limit
捕获变量的延长生存期
对于一个捕获变量,只要还有任何委托实例在引用它,它就会一直存在
局部变量实例化
每声明一次局部变量,它就被实例化一次。
捕获变量的使用规则和小结
- 只在复杂情况下使用
- 捕获有for或foreach语句声明的变量之前,思考委托是否需要在循环迭代结束后延续,不是则在循环内另建一个变量来复制想要的值。
- 若创建多个委托实例,且捕获了变量,思考是否希望它们捕捉同一个变量
- 如果捕获的变量不发生改变,无需担心