在"委托、Lambda表达式、事件系列02,何时该用委托"一文中,使用委托让代码简洁了很多。
html
namespace ConsoleApplication2
{internal delegate bool MyCalculateDelegate(int val);class Program
{static void Main(string[] args){IEnumerable<int> source = new List<int>(){2, 3, 4, 5, 6, 7, 8, 9,10, 11};MyCalculateDelegate del = LessThanFive;var result = GetNumbers(source, del);foreach (int n in result){Console.WriteLine(n);}}static IEnumerable<int> GetNumbers(IEnumerable<int> numbers, MyCalculateDelegate del){foreach (int number in numbers){if (del(number)) yield return number;}}static bool LessThanFive(int val){return val < 5;
}static bool LessThanTen(int val){return val < 10;
}}}
但是,以上LessThanFive方法和LessThanTen方法的输入参数、输出类型、以及实现逻辑都是一致的,有没有一种形式能够替代它们?这正是Lambda表达式登场的时候!Lambda表达式是匿名委托,以=>分隔,左边是输入参数,右边是实现过程。闭包
namespace ConsoleApplication2
{internal delegate bool MyCalculateDelegate(int val);class Program
{static void Main(string[] args){IEnumerable<int> source = new List<int>(){2, 3, 4, 5, 6, 7, 8, 9,10, 11};var result = GetNumbers(source, n => n < 5);foreach (int n in result){Console.WriteLine(n);}}static IEnumerable<int> GetNumbers(IEnumerable<int> numbers, MyCalculateDelegate del){foreach (int number in numbers){if (del(number)) yield return number;}}}}
以上,使用Lambda表达式又让代码简洁了很多!GetNumbers的实参n => n < 5,就是一个Lambda表达式,它符合委托MyCalculateDelegate的定义,输入参数是整型,输出是bool类型。spa
其实,lambda表达式n => n < 5是一种"语法糖",内部仍是执行了以下代码:htm
......MyCalculateDelegate del = LessThanFive;var result = GetNumbers(source, del);......static bool LessThanFive(int val){return val < 5;
}
这一点能够从IL层面看出。使用Reflector进行反编译:blog
private static void Main(string[] args){List<int> <>g__initLocal0 = new List<int>();<>g__initLocal0.Add(2);<>g__initLocal0.Add(3);<>g__initLocal0.Add(4);<>g__initLocal0.Add(5);<>g__initLocal0.Add(6);<>g__initLocal0.Add(7);<>g__initLocal0.Add(8);<>g__initLocal0.Add(9);<>g__initLocal0.Add(10);<>g__initLocal0.Add(11);IEnumerable<int> source = <>g__initLocal0;
IEnumerable<int> result = GetNumbers(source, (CS$<>9__CachedAnonymousMethodDelegate2 != null) ? CS$<>9__CachedAnonymousMethodDelegate2 : (CS$<>9__CachedAnonymousMethodDelegate2 = new MyCalculateDelegate(Program.<Main>b__1)));foreach (int n in result){Console.WriteLine(n);}}
以上,因为n => n > 5符合委托MyCalculateDelegate的定义,在内部建立了一个MyCalculateDelegate类型的委托,而后把一个编译器生成的方法<Main>b__1赋给了委托变量。事件
[CompilerGenerated]private static bool <Main>b__1(int n){return (n < 5);
}
<Main>b__1方法是由编译器帮咱们自动生成的。get
总结:lambda表达式实际上是"语法糖",源代码被编译的时候,编译器会自动帮咱们生成一个符合委托定义的方法,而后把该方法赋给委托。编译器
“委托、Lambda表达式、事件系列”包括:string