LINQ中的"延迟查询"特性【转】

本文转载自:LINQ中的"延迟查询"特性

详细了解“延迟查询”:C#学习笔记(八)—–LINQ查询之延迟执行

很多标准查询操作符的设计原型都是返回一个IEnumerable<T>类型的序列, 这些标准查询操作实际上不会在代码执行到那一行的时候就返回一个序列, 事实上返回的是一个对象. 当在枚举(比如foreach)这个对象的时候会从IEnumerable<T>序列中生成一个元素, 这个时候才会真正执行查询操作. 这就是所谓的"延迟查询".


 小例子证明"延迟查询"的存在性

var numbers = new List<int>();
numbers.Add(1);
IEnumerable<int> query = numbers.Select(n => n * 10);
foreach (int n in query)
    Console.Write(n+"/n");//10
numbers.Add(2);
foreach (int n in query)
    Console.Write(n + "|"); // 10|20|
Console.ReadKey();

 两次输出结果分别为:10 和 10|20. 由此可见只有在枚举items的时候才会真正的执行查询操作. 如果没有延迟查询, 两次输出的结果应该是相同的.


 避免"延迟查询"的方法

可以使用一个不返回IEnumerable<T>数据类型的转换操作符, 如ToArray, ToList, ToDictionary或ToLookup, 这样查询操作就不会被延迟了. 同样是上面例子的, 通过ToList操作符返回一个List<int>型序列, 就不会产生"延迟查询"的现象:

var numbers = new List<int>();
numbers.Add(1);
IEnumerable<int> query = numbers.Select(n => n * 10).ToList();//添加了tolist
foreach (int n in query)
    Console.Write(n+"/n");//10
numbers.Add(2);
foreach (int n in query)
    Console.Write(n + "|"); // 10
Console.ReadKey();

这样两次输出的结果就都为10了.


 "延迟查询"可能导致的错误

因为有了延迟, 被枚举的时候才会真正的去执行一个查询, 因此如果程序编译通过了但绝对不意味着这个查询就是没事儿的. 比如查询一个字符串数组里面, 每个元素的第3个字符是什么的时候, 如果某个字符串长度<3, 那么在运行的时候就会报错, 而程序在编译的时候是没有问题的.

原文地址:https://www.cnblogs.com/gdvxfgv/p/10445029.html