从C# 3.0说以人为本(四)—— Lambda表达式

时间:2021-11-29 19:06:50

 重新回到那个用了很多次的语句:
  1. IEnumerable<int> numQuery = numbers.Where((number) => number % 2 == 0);

 
我们知道了Where是扩展方法,但是后面的(number) => number % 2 == 0又是什么?功能一看就明白了,就是选择是偶数的数字,但是深层机理又是什么样子的?
 
      查一下MSDN,原来这种表达式也是3.0新增的东东,叫Lambda表达式。它的语法小凡就不再介绍,MSDN中有很详细的说明,再说也是狗尾续貂。但是,除了用Lambda表达式,像这样的函数还能传入什么形参?是不是只能用Lambda表达式了呢?
      答案当然是不会的,如果真的是这样,那限制就太大了不是吗?再查一下MSDN吧(MSDN果然才是解决问题的王道口牙),我们看到Where是被重载了好几次的。
 
  名称 说明
Where(Expression<(Of <(Func<(Of <(TElement, Boolean>)>)>)>)) 基于谓词筛选值序列。 (由 Queryable 定义。)
Where(Expression<(Of <(Func<(Of <(TElement, Int32, Boolean>)>)>)>)) 基于谓词筛选值序列。将在谓词函数的逻辑中使用每个元素的索引。 (由 Queryable 定义。)
Where(Func<(Of <(TElement, Boolean>)>)) 基于谓词筛选值序列。 (由 Enumerable 定义。)
Where(Func<(Of <(TElement, Int32, Boolean>)>)) 基于谓词筛选值序列。将在谓词函数的逻辑中使用每个元素的索引。 (由 Enumerable 定义。)


 
其中有一个东西每个重载都会出现,就是Func<(Of <(TElement, Int32, Boolean>)>),好像是一个泛型,当然略有区别,有的是传入2个有的是传入3个类型。那Func<(Of <(TElement, Int32, Boolean>)>)又是什么?再深入一下,原来是一个委托!

  1. public delegate TResult Func<T1, T2, TResult>( T1 arg1, T2 arg2 ) 

委托是什么我想大家都用过,其实说穿了可以把它当成一个函数的指针(当然并不完全是,委托不等于函数指针,详细请见《.NET Framework 编程》一书)。
走到这一步,恐怕大家都明白了,其实就是一个函数,这个函数用bool类型作为返回值,也就是判断where条件是不是匹配。
针对上面那行代码,我们用纯委托的方式再重现一次。

首先定义一个方法,完成校验偶数的功能:

  1. private static bool IsEvenNumber(int number){     return number % 2 == 0;}

 

然后把一开始的那行代码替换成

  1. IEnumerable<int> numQuery = numbers.Where(new Func<int,bool>(IsEvenNumber));

OK,效果是完全一样的。这说明其实Lambda表达式其实在某种程度上就是一个匿名的函数,并且通过编译器来自动识别类型换成泛型的委托。小凡认为,Where的内部代码逻辑就是遍历每个numbers中的数字,并且调用传入的委托方法来进行校验。其实很简单不是吗?

虽然内部机理很简单,但是如果真的要用委托,可能代码量马上就增加了,相反用了Lambda表达式(当然事实上也需要编译器的支持),就能又简单又快捷的完成工作,为程序员考虑的语言才是好语言。

至此,从C# 3.0说以人为本就全部介绍完了,其中介绍了C# 3.0新增的LINQ和Lambda表达式,其它的一些新特性比如匿名类型等等就不描述了,谢谢大家。