写在前面
其实在09年就已经学习过LINQ了,并被她那优美的语法所吸引,只是现在所在的公司还在使用VS2005在.Net2.0的框架下面的开发,所以LINQ也很久没有用过了,最近看部门的同事对这个有些兴趣,所以打算整理点东西出来跟大家一起做个分享。
什么是LINQ
LINQ是Language Integrated Query的简称,它是集成在.NET编程语言中的一种特性。已成为编程语言的一个组成部分,在编写程序时可以得到很好的编译时语法检查,丰富的元数据,智能感知、静态类型等强类型语言的好处。并且它同时还使得查询可以方便地对内存中的信息进行查询而不仅仅只是外部数据源。
LINQ包括LINQ to Objects,LINQ to SQL ,LINQ to XML ,LINQ to DataSet等,本篇从LINQ to Objects开始了解LINQ的皮毛。
开始LINQ前你要知道的
扩展方法
顾名思义就是对现有类进行扩展的的方法,扩展方法可以在不修改现有类的情况下,为现有类增加公共的接口(不是C#中的interface)。
扩展方法本质上是一个静态方法,不同之处在于它的第一个参数必须有this关键字声明,并且第一个参数的类型即为要扩展的类型。如
- public static double ToDouble(this string source)
- {
- double res = 0d;
- double.TryParse(source, out res);
- return res;
- }
-
- public static void SimpleExtesionMethod()
- {
- double d = "12345.54321".ToDouble();
- Console.WriteLine(d);
- }
这里是个简单的将字符串转为double类型的扩展方法,只要引用了该方法的命名空间,则都可以直接用string类型来调用ToDouble方法。
扩展方法是后文的基础,C#3.0中的LINQ的实现都是基于扩展方法,通过对IEnumerable<T>接口(LINQ to Objects)的扩展和对IQueryable<T>的扩展来实现LINQ的相关功能,而LINQ的相关关键字最终都是转化为对IEnumerable<T>(IQueryable<T>)的调用。
Lambda表达式
lambda表达式其实就是就是.net2.0中的匿名方法,然后再3.0中以一种更优美的姿态呈现出来。
lambda表达式的基本语法为
(参数列表) =>{语句块;} 或者
( 参数列表) =>表达式
当参数列表中只有一个参数的时候,圆括号可以省略
- Func<string, string> func = x => x + x;
- Console.WriteLine(func("a"));
Var:隐式类型化变量
使用与可以由编译器推导出的变量的声明,不需要显式指定对象的类型。
- var container = new List<string> { "张三", "李四", "王五" };
- IEnumerable<string> query = from name in container
- select name;
上例中由于定义中已经指明了对象的类型,声明中已经完全没有必要使用显示的类型定义,所以可以使用var关键字。
对于匿名对象
- var test = new { Name = "Sth.", Type = "UnKnown" };
由于无法用一个类型类声明匿名对象,此时可以用var是声明。
注意var只是省下了显式声明的过程,而C#本身就是静态语言,所以var所声明的变量的类型已经确定任然是不能改变的,亦即,var并非是变体类型。
LINQ对谁适用
LINQ的语法通过System.LINQ下面的Enumerable类提供支持,通过观察他的签名,你就会发现他为IEnumerable<T>实现了一系列的扩展方法,也就是说,只要是实现了IEnumerable<T>的对象都可以使用LINQ的语法来查询。
而对于只实现了IEnumerable接口而没有实现IEnumerable<T>的对象可以通过
- public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source);
来将IEnumerable接口转为IEnumerable<T>(例如ArrayList)。
LINQ中的关键字
在C#3.0中,为LINQ引入了一些新的关键字,他们是:
- from join where group into let orderby select
熟悉Sql的同学看着是不是有些眼熟呢,其实在LINQ中他们的涵义和在SQL中类似的,所以会很容易理解的。接下来的时间,简单介绍下这些关键字的使用。
from
from子句是一个LINQ查询的开始,任何一个LINQ语句都是以from开始,from子句指定查询的容器,和在此语句有效的局部变量(用来指定容器中的一项,from子句的效果很类似于foreach)。from子句的语法为
- from local in containerlocal
就是在此LINQ语句中的局部变量,由于container必须为IEnumerable<T>,他的类型可以由container推导出来(即T)。上一段简单的例子:
- var container = new List<string> { "张三", "李四", "王五" };
- var query = from name in container
- select name;
-
- foreach (string name in query)
- {
- Console.WriteLine(name);
- }
输出
张三
李四
王五
如果container仅仅实现IEnumerable而没有实现IEnumerable<T>,则需要显式指定局部变量的类型,或者是使p