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中group by
- linq中延迟执行
- 使用 LINQPad 调试linq以及lambda表达式
- 如何查看linq生成的sql
- list使用linq排序
- linq distinct去重
- linq中join用法
- linq xml 查询
- Linq中的TakeWhile和SkipWhile
- linq中AsEnumerable和AsQueryable的区别
- Linq中select查询
- linq 数据类型转换
- Linq中where查询
- linq to sql 中Concat、Union、Intersect、Except
- datatable linq查询
- LINQ TO SQL 中join
- 爱情能当饭吃吗(爱情能当饭吃吗说说)
- 白T恤穿法(白t恤)
- 你怎么忘了是说先爱我(你怎么忘了如何爱我)
- 做技术难吗(技术难不难)
- 林心如是谁(林心如是谁演的)
- 泰国安全吗(泰国安全吗2023)
热门推荐
- mysql8.0详解(MySQL 8.0 的 5 个新特性,太实用了!)
- vue引入axios(vue封装axios的几种方法)
- phpredis怎么实现任务(PHP swoole和redis异步任务实现方法分析)
- android系统如何截屏(Android实现矩形区域截屏的方法)
- mysql的常见优化(详解GaussDB for MySQL性能优化)
- mysql order by id查询变慢(MySQL不使用order by实现排名的三种思路总结)
- php连接数据库拒绝使用域名(访问php时提示内存位置访问无效的解决办法和思路分析)
- php协议使用教程学习(php中的钩子理解及应用实例分析)
- dedecms漏洞防范(浅析DedeCMS投票模块漏洞的解决方法)
- linux如何使用gdb调试(Linux下如何使用gdb调试core文件)