zoukankan      html  css  js  c++  java
  • LINQ之延迟加载及其原理

           这是LINQ(集成化查询)的继续及补充,在前面我已经介绍过,在LINQ中,一个重要的特性就是延迟加载,是指查询操作并不是在查询运算符定义的时候执行,而是在真正使用集合中的数据时才执行(如:在遍历集合时调用MoveNext方法时)。下面是一个简单的实例:

                var num = new List<int>();
                num.Add(1);
                IEnumerable<int> query = num.Select(n => n * 10);
                num.Add(2);
                foreach (int n in query)
                    Console.WriteLine(n);

    结果输出10   20.在上面的例子中,在创建查询语句后又向集合中加入新元素,这个新元素最终也出现在查询结果中。这就是因为查询语句是在遇到foreach之后才真正执行的,再例如:

                Action a = () => Console.WriteLine("Foo");
                //没有在控制台输出任何内容
                a();
                //延迟执行,输出Foo

    绝大部分标准的LINQ查询运算符都具有延迟加载这种特性,但也有例外:

    •  那些返回单个元素或返回一个数值的运算符,如First或Count。
    • 转换运算符:ToArray,ToList,ToDictonnary,ToLookup。

    以上这些运算符都会触发LINQ语句立即执行,因为它们的返回值类型不支持延迟加载。

    延迟加载的工作原理

       LINQ查询运算符之所以有延迟加载功能,是因为每个返回值不是一般的数组或集合,而是一个经过封装的序列,这种序列通常情况下并不直接储存数据元素,它封装并使用运行时传递给它的集合,元素也由其他集合来储存,它实际上只是维护自己与数据集合的一种依赖关系,当有查询请求时,再到它以来的序列中进行真正的查询。查询运算符实际上是封装一系列的转换函数,这种转换函数可以将与之关联的数据转换为各种形式的序列。如果输出集合不需要转换的话,那么就不用执行查询运算符封装的转换操作,这个时候查询运算符实际上就是一个委托,进行数据转发而已。

    例如调用Where运算符的时候,在Where内部所做的操作非常简单,根据Lambda表达式中指定的查询条件,对输入集合重新进行了筛选,保留那些符合条件的元素指针引用,当外部遍历Where的返回值时,Where回到它所关联的集合中进行真正的查询,然后返回查询结果。

    IEnumerable<int> lessThanTen = new int[] { 5, 12, 3 }.Where(n => n < 10);

    当执行lessThanTen操作时,实际上,就是使用where运算符对封装序列进行筛选。

    当需要使用一些有特殊功能的运算符时,我们可以自定义实现。例如下面这个实例所示,实现一个自定义的Select运算符:

            public static IEnumerable<TResult> Select<TSource,TResult>(
                this IEnumerable<TSource> source,Func<TSource,TResult> selector)
            {
                foreach (TSource element in source)
                    yield return selector(element);
            }

    上面这个方法实际上就是在循环中返回yield类型的元素。所以当调用Select和Where查询运算符时,内部操作就是创建一个序列,然后将查询得到的元素存入这个新的序列中。

    其实,在LINQ中,延迟加载特性是很重要的,这种设计将查询的转换和查询的执行进行了解耦,这使得我们可以将查询分成多个步骤来创建,有利于查询表达式的书写,而且在执行的时候按照一个完整的结构去查询,减少了对集合的查询次数,这种特性对数据库查询尤其重要。

  • 相关阅读:
    利用avicap32.dll实现的实时视频传输
    异常错误:在可以调用 OLE 之前,必须将当前线程设置为单线程单元(STA)模式
    很不错的python 机器学习资源
    基于C#的机器学习--目录
    C#WinForm无边框窗体移动----模仿鼠标单击标题栏移动窗体位置
    C# WinForm窗体控件GroupBox修改边框颜色控件
    wireshark抓包新手使用教程
    Winform开发框架之权限管理系统功能介绍
    自定义控件开发的调试及DesignMode的状态处理
    Winform开发框架之权限管理系统改进的经验总结(4)--用户分级管理
  • 原文地址:https://www.cnblogs.com/czx1/p/4947855.html
Copyright © 2011-2022 走看看