C#学习笔记—LINQ to Object
1、LINQ特有的编程结构
隐式类型本地变量:C#的var关键字允许定义不显式指定实际数据类型的本地变量。不过由于编译器将根据初始值推断其数据类型,所有该变量仍然是强类型的。
对象和集合初始化语法:它允许我们在创建类或结构变量的同时设置其属性。
Lambda表达式:C#Lambda操作符(=>)可以用来构建Lambda表达式,并且在调用以强类型的委托作为参数的方法时,也十分有用。
扩展方法:C#扩展方法不使用子类就能够像已知类中添加新的功能。同样,它还可以向不能有子类的密封类和结构中添加新的功能。在编写扩展方法时,第一个参数必须使用this限定符,用来表示被扩展的类型。扩展方法只能定义在静态类中,并且必须使用static关键字声明为静态方法。
匿名类型:该特性可以快速建立数据的“结构”,编译器将根据名称/值对的结合在编译时生成新的类。该类型是基于值的语义构建的,因此System.object中的每个虚方法都要重写。要定义一个匿名类型,可以声明一个隐式类型变量,并使用对象初始化语法指定数据的结构。
2、LINQ查询表达式是强类型的(跟传统的SQL语句有所不同)。
3、核心LINQ程序集
System.Core.dll:定义了代表核心LINQ API的类型;
System.Data.DataSetExtensions.dll:定义了许多类型来将ADO.NET类型融入LINQ变成范式;
System.Xml.Linq.dll:提供了使用LINQ处理XML文档数据所需的功能。
4、将LINQ查询应用于原始数组
1 static void Main(string[] args)
2 {
3 QueryOverStrings();
4 Console.ReadLine();
5 }
6
7 static void QueryOverStrings()
8 {
9 //假定我们有一个字符串数组
10 string[] currentVideoGames = { "Morrowind", "Uncharted2", "Fallout 3", "Daxter", "System Shock 2" };
11
12 //构建一个查询表达式,来代表数组中有一个空格的项
13 IEnumerable<string> subset = from g in currentVideoGames where g.Contains(" ") orderby g select g;
14
15 //输出结果
16 foreach (string s in subset)
17 Console.WriteLine(s);
18 }
一般来说,在获取LINQ查询的结果集时,应该总是使用隐式类型。但要记住的是,在绝大多数情况下,真正的返回值是实现了泛型IEnumerable<T>接口的类型。
static void QueryOverInts()
{
int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8};
//只输出小于10的项
//使用隐式类型
var subset = from i in numbers where i < 10 select i;
foreach (var i in subset)
Console.WriteLine(i);
ReflectOverQueryResults(subset);
}
5、LINQ和扩展方法:虽然System.Array并没有直接实现IEnumerable<T>接口,但它通过静态的System.Linq.Enumerable类类型间接地得到了该类型所需的功能,同时还得到了许多其他的与LINQ相关成员。
6、延迟执行的作用:有关LINQ查询表达式另一个重要的地方是在我们迭代内容之前,它们不会真正进行运算,严格的说叫做延迟执行。这个方式的好处在于可以为相同的容器多次应用相同的LINQ查询,而始终可以获得最新的最好的结果。
1 static void QueryOverInts()
2 {
3 int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8};
4
5 //只输出小于10的项
6 //使用隐式类型
7 var subset = from i in numbers where i < 10 select i;
8
9 foreach (var i in subset)
10 Console.WriteLine(i);
11 Console.WriteLine();
12
13 //修改一些数据
14 numbers[0] = 4;
15
16 //再一次运算
17 foreach (var j in subset)
18 Console.WriteLine(j);
19 Console.WriteLine();
20
21 ReflectOverQueryResults(subset);
22 }
7、立即执行的作用:如果希望foreach逻辑外部运算LINQ表达式,可以调用由Enumerable类型定义的许多扩展方法来完成。Enumerable定义了诸如ToArray<T>()、ToDictionary<TSource,TKey>()以及ToList<T>()在内的许多扩展方法。在调用这些方法的同时将执行LINQ查询,以获取数据快照。然后这些数据快照就可以独立进行操作了:
1 static void ImmediateExecution()
2 {
3 int[] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };
4
5 //立即获取数据为int[]
6 int[] subsetAsIntArray =
7 (from i in numbers where i < 10 select i).ToArray();
8
9 //立即获取数据为List<int>
10 List<int> subsetAsListOfInts =
11 (from i in numbers where i < 10 select i).ToList();
12 }
整个LINQ表达式用圆括号括起来,这样就能将它强制转换为正确的实际类型来调用Enumerable的扩展方法。C#编译器可以准确检测泛型项的类型参数,我们不需要指定类型参数。
8、返回LINQ查询的结果
9、将查询应用到集合对象
10、C#LINQ查询操作符