linq中延迟执行
linq中延迟执行
linq中延迟执行LINQ执行过程的一个重要特征是延迟执行,Linq的大多数查询运算符并不是在构建的时候就立即执行,所有标准查询运算符均为延时执行,但是有的运算符不支持延时执行的机制,而是立即执行,如Count 、ToAarry、toLookup等。
一、LINQ延迟执行优点
1、LinQ语法,只是构造了“查询语句”,真正执行这种语句的是IEnumerator<T>里的GetEnumerator()方法,因此,当调用GetEnumerator(),就真正执行一次LinQ获取数据,多次调用GetEnumerator(),就多次执行LinQ。我们可以中途修改LinQ(即修改了“查询语句”),下次执行GetEnumerator()方法的结果就会相应地改变了。
例如
List<Employee> emps = new List<Employee>() { new Employee(){ id="1001", name="ivan", dept="isd", tel="1021"}, new Employee(){ id="1002", name="ivan", dept="isd", tel="1021"}, }; var query = from e in emps select e; emps.Add(new Employee(){ id="1003", name="ivan", dept="isd", tel="1021"}); Console.WriteLine(query.Count()); //输出结果: 3
2、可以为相同的容器多次应用相同的Linq查询,而始终获得最新的结果。
3、可以使用Linq延迟执行将额外信息的检索操作延迟到你确实需要检索它们时再进行。
二、linq延迟执行的影响
1、重复执行
当我们重复遍历查询结果时,查询会被重复执行
static void TestReevaluation()
{
var numbers = new List<int>() { 1, 2 };
IEnumerable<int> query = numbers.Select(n => n * 10); // Build query
foreach (int n in query) Console.Write(n + "|"); // 10|20|
numbers.Clear();
foreach (int n in query) Console.Write(n + "|"); // <nothing>
}
有时候,重复执行对我们说可不是一个优点,理由如下:
(1)、当我们需要在某一个给定的点保存查询的结果时。
(2)、有些查询比较耗时,比如在对一个非常大的sequence进行查询或者从远程数据库获取数据时,为了性能考量,我们并不希望一个查询会被反复执行。
这个时候,我们就可以利用转换运算符,比如ToArray、ToList来避开重复执行,ToArray把查询结果保存至一个Array,而ToList把结果保存至泛型List<>
static void TestDefeatReevaluation()
{
var numbers = new List<int>() { 1, 2 };
List<int> timesTen = numbers
.Select(n => n * 10)
.ToList(); // Executes immediately into a List<int>
numbers.Clear();
Console.Write(timesTen.Count); // Still 2
}
2、变量捕获
如果查询的lambda表达式引用了程序的局部变量时,查询会在执行时对变量进行捕获。这意味着,如果在查询定义之后改变了该变量的值,那么查询结果也会随之改变。
static void TestCapturedVariable()
{
int[] numbers = { 1, 2 };
int factor = 10;
IEnumerable<int> query = numbers.Select(n => n * factor);
factor = 20;
foreach (int n in query)
Console.Write(n + "|"); // 20|40|
}
三、如何让Linq查询立即执行呢
Enumerable定义了诸如ToArray<T>()、ToDictionary<TSource, TKey>()、ToList<T>()在内的许多扩展方法,它们允许我们以强类型容器来捕获Linq查询结果。
由于每调用一次GetEnumerator(),就执行一次LinQ,在“查询语句”不变的情况下,就会出现多次重复的查询操作(结果一样),这种情况下,有必要使用ToList(),ToArray()这样的方法把结果固定下来(其实也就是调用GetEnumerator方法返回结果来装载List,Array),然后操作相应的List,Array,避免重复的查询操作。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestVar
{
class Program
{
static void Main(string[] args)
{
int[] intAry = new int[] { 1, 2, 3, 4, 5, 6 }; //使用强类型立即获取查询结果
List<int> intList = (from x in intAry
where x % 2 == 0
select x).ToList(); //输出查询结果 foreach (int v in intList)
{
Console.Write(v.ToString() + " ");
}
Console.ReadKey();
}
}
}
- linq 排序
- linq to sql 中Concat、Union、Intersect、Except
- linq中let
- linq xml 查询
- linq not in 查询
- Linq中的TakeWhile和SkipWhile
- linq 数据类型转换
- linq中group by
- linq中AsEnumerable和AsQueryable的区别
- linq中延迟执行
- LINQ TO SQL 中join
- linq distinct去重
- datatable linq查询
- Linq操作Datable
- Linq中select查询
- list使用linq排序
- 庆八一,重读经典红色语录,感悟互联网发展硬道理(重读经典红色语录)
- TVB新剧《黯夜守护者》将播,陈展鹏陈炜首次合作探讨人性(TVB新剧黯夜守护者将播)
- 新晋小花被称女版吴卓羲 将取代滕丽名成为TVB新一代御用女警(新晋小花被称女版吴卓羲)
- 艺人吴卓羲10年警察生涯,演足10年阿Sir,系咩玩法(艺人吴卓羲10年警察生涯)
- 菲律宾潜水(菲律宾潜水价格)
- 泰国人妖(变性手术生殖器要割掉吗)
热门推荐
- php 设置sessionid生成机制(PHP Cli 模式设置进程名称的方法)
- python实例之pyqt5多窗口实现(python+pyqt5编写md5生成器)
- dedecms导入doc插件(DEDECMS教程之静态模板类类文件)
- pythonssh登录服务器(对python 通过ssh访问数据库的实例详解)
- 云服务器主要内容(云服务器的应用优势分析,你知道有哪些优势吗?)
- vue手动清除keepalive缓存(vue中keep-alive组件的用法示例)
- js实现div(javascript拖曳互换div的位置实现示例)
- VPS/云服务器使用3389端口远程连接管理图文教程(Windows)(VPS/云服务器使用3389端口远程连接管理图文教程Windows)
- linq 排序
- 宝塔怎么开放端口(宝塔面板修改默认端口以及一些常用端口的安全设置)