Delegate

Statement Lambda
替代简单委托实例的一种方法
(paras…) => {block with return statement}在类型很显然的情况,不需要显式说明参数类型:
public static void BubbleSort(int[] items, Func<int, int, bool> compare) { // ... } // call BubbleSort(items, (first, second) => { return first < second; })
Expression Lambda
(paras) => expression 注意事项:
- Lambda表达式本身没有类型,不能访问其任何成员(包括object的方法)
- 不能在内部用跳转语句跳转到外部
- 编译器确定性赋值分析机制在Lambda表达式内部检测不到对外部局部变量进行初始化的情况
- 比如在lambda表达式内部对一个未初始化的变量赋值,此时编译器仍认为这个变量是未初始化的
Anonymous Method
C#2.0之前不支持Lambda表达式,只引入了Lambda表达式
BubbleSort(items, delegate(int first, int second) { return first < second; })
无参匿名方法:省去整个函数参数列表,兼容任何返回某类型的委托
古老写法,不常用
delegate {return Console.ReadLine() != "";}
委托的逆变和协变
参数向下兼容(子 = 父),返回值向上(父 = 子)
Func<object, string?> func1 = (object data) => data.ToString(); Func<string, object?> func2 = func1;
外部变量
被lambda表达式捕捉的外部变量生存期会被延长
避免在lambda表达式中捕捉循环变量
Lambda和匿名函数的内部机制
编译器会将这俩转换为特殊的隐藏类、字段和方法
没有外部变量就直接生成静态方法,有则会生成一个sealed class(或者说,闭包)
class DelegateSample { // 这是lambda表达式在CIL中生成的闭包 private sealed class _LocalsDisplayClass_00000001 { public int comparisonCount; public bool _AnonymousMethod_0000000(int first, int second) { comparisonCount++; return first < second; } } // ... static void Main(string[] args) { _LocalsDisplayClass_00000001 locals = new _LocalsDisplayClass_00000001(); locals.comparisonCount = 0; int[] items = new int[5]; /* 原代码: BubbleSort(items, (first, second) => { comparisonCount++; return first < second }) */ BubbleSort(items, locals._AnonymousMethod_0000000); Console.WriteLine("Items were compared {0} times.", locals.comparisonCount); } }
表达式树
?