LINQ学习笔记:结构化且类型安全的查询
LINQ (Language Integrated Query), 允许你编写结构化并且是类型安全的查询去访问本地对象集合和远程的数据源. 是.NET Framework 3.5提供的一个新特性.
LINQ 允许你查询任何实现了IEnumerable<>的集合, 可以是一个数组(Array), 列表(List), XML DOM或者是远程的数据源(例如SQL SERVER). LINQ提供了编译时类型检查和动态查询组合的好处.
用于支持LINQ的核心类型主要定义在System.Core这个程序集(Assembly)的System.Linq和System.Linq.Expressions命名空间中
LINQ的基本数据单元是序列(sequence)和元素(element). 一个序列可以是任何实现了范型IEnumerable接口的对象, 而一个元素是序列中的每一项. 看一个简单的例子:
string[] names = {“James”, “Tom”, “Harris”};
这个例子中names是一个序列, 和James, Tom和Harris是元素. 我们把这样一个序列叫做本地序列因为它代表了一个存在于内存当中的本地对象集合.
一个查询操作是一个转换序列的方法. 一个典型的查询操作接受一个输入序列并且将其转换成一个输出序列.在System.Linq中的Enumberable类中, 大于存在40个左右的查询操作方法, 全部都被实现为静态的扩展方法, 他们被称为标准查询操作.
一个查询是一个通过查询操作方法转换了序列的表达式. 最简单的查询包括了一个输入序列和一个操作方法. 举个例子, 我们可以对一个简单的数组应用一个Where操作方法以便过滤出那些长度不小于4个字符的元素.
1: string[] names = { “Tom”, “Dick”, “Harry” };
2:
3: IEnumerable<string> filteredNames = System.Linq.Enumerable.Where(names, n => n.Length >= 4);
4:
5: foreach (string n in filteredNames)
6:
7: Console.Write(n + “|”); // Dick|Harry|
因为标准的查询操作都被实现为扩展方法, 我们可以直接在names上面调用Where方法, 犹如它是一个实例方法一样:
IEnumerable<string> filteredNames = names.Where(n => n.Length >= 4)
以下是一个完整的例子, 为了能够通过编译, 你必须导入System.Linq命名空间:
1: using System;
2:
3: using System.Linq;
4:
5: class LinqApp
6: {
7:
8: static void Main()
9:
10: {
11:
12: string[] names = { “Tom”, “Dick”, “Harry” };
13:
14: IEnumerable<string> filteredNames = names.Where(n => n.Length >= 4);
15:
16: foreach (string name in filteredNames)
17:
18: Console.Write(name + “|”);
19:
20: }
21:
22: }
23:
24: // RESULT: Dick|Harry|
通过新的关键字var, 我们还可以使查询语句更简短一些:
var filteredNames = names.Where(n => n.Length > = 4);
大多数的查询操作方法都接受一个Lambda表达式作为输入参数, Lamdba表达式用于指导和塑造查询, n => n.Length >= 4就是我们上述方法中用到的Lamdba表达式. 输入参数将会响应到每一个元素, 在这个例子中, 输入参数n代表在数组中的每一个元素, 并且它的类型是string. Where操作方法要求Lambda表达式返回一个bool值, 如果返回true, 表示该元素将被包含进输出序列中.
另外在C#当中还定义了一种特殊的语法用于编写查询, 成为复合查询语法, 一个例子如下:
IEnumerable<string> theName = from n in names where n.Contains(“T”)
select n;
Lambda语法和复合查询语法是互补的. 待续!