LINQ 学习笔记2
第2章 C# Language Enhancements For LINQ
C# 语言新特性
1.Lambda 表达式
2.表达式树
3.var 关键字,对象 和 集合初始化 ,匿名类
4.拓展方法
5.部分方法
6.查询表达式
一、Lambda表达式
Lambda表达式的引入是为了简化匿名方法的使用,而匿名方法又是为了简化委托代码写在别处,复用率又不高的代码段。
书中的例子:
使用命名方法(Named Methods)
在C# 2.0之前,可以使用委托(delegate)来完成这项工作。比如考虑这样一个应用,对数组元素按照一定的规则进行过滤,对于通用模块,可以写成下面的样子:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
然后搞算法的人就把过滤算法写成函数,比如下面的这样:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
这个IsOdd()方法,就是描述算法的named method。在实际的调用过程中,caller调用的是Common类的FilterArrayOfInt()方法,该方法的第二个参数,就是一个过滤器算法的委托(函数指针)。所有的过滤器算法必须是具有相同的参数和返回值类型。在调用FilterArrayOfInt()方法的时候,同时把描述算法的IsOdd()作为参数,代入委托,这样一个事件就搞定了。
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
结果当然是1、3、5、7、9。算法的实现者可以写出各种不同的filter,如此代入即可。
使用匿名方法(Anonymous Methods)
在C# 2.0中,引入了匿名方法,可以将代码内联来替换委托。上面的示例中Main()方法里的oddNums赋值可以改写如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
在委托参数的地方可以简单地用这种内联的形式,由于没有定义一个确定名称的方法,就称作匿名方法。对于不怎么需要复用的代码,这种手段可以极大简化程序结构,但降低了可读性。对于比较复杂的函数体就很suck了。。
使用Lambda表达式
Lambda表达式的一般形式,是由一组由逗号分隔的参数列表,跟着一个lambda操作符,再跟着一个表达式或者语句块。多个输入参数的情况下需要用括号来包围。在C#中,lambda操作符是=>,因此,在C#中的lambda表达式应该是这个样子的:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
再回过头看delegate的部分,一个delegate实际上就是指定了输入的参数格式以及返回值的格式,那么在lambda表达式中,就对应着=>左边的那一坨以及语句体里return的那个东东。在前面的例子中,输入是一个int型数据,返回一个bool量,比如:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
这个表达式可以读作“x goes to x.Length >0”,或者“输入x,返回x.Length>0”。下面的lambda表达式可以返回输入参数的长度:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
那么delegate就应该指定返回int型值。对于多个输入变量的,比如:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
再复杂一点的:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
好,下面我们来改造前面的那个例子,算法设计者所设计的lambda表达式必须满足委托的声明:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
则可以将oddNums的赋值写成这样:
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
结果当然也会和前面完全一样。