zoukankan      html  css  js  c++  java
  • C#编程之IList<T>、List<T>、ArrayList、IList, ICollection、IEnumerable、IEnumerator、IQueryable 和 IEnumerable的区别

    额。。。今天看了半天Ilist<T>和List<T>的区别,然后惊奇的发现使用IList<T>还是List<T>对我的项目来说没有区别。。。
     在C#中,数组、ArrayList都能够存储一组对象,那么三者到底有什么样的区别呢?

    数组

    数组在C#中最早出现的。在内存中是连续的,所以它的索引速度非常快,而且赋值与修改元素也很简单。
    1. string[] s=new string[2];  
    2.   
    3. //赋值  
    4. s[0]="a";  
    5. s[1]="b";  
    6. //修改  
    7. s[1]="a1";  
    string[] s=new string[2];
    
    //赋值
    s[0]="a";
    s[1]="b";
    //修改
    s[1]="a1";
    
            但是数组存在一些不足的地方。在数组的两个数据间插入数据是非常麻烦的,而且在声明数组的时候必须指定数组的长度,数组的长度过长会造成内存浪费,过短会造成数据溢出。如果在声明数组时我们不清楚数组的长度就会很麻烦。

    ArrayList

            针对数组的这些缺点,C#中最先提供了ArrayList对象来解决这些问题。
            ArrayList是命名空间System.Collections下的一部分,在使用该类时必须进行引用,同时继承了IList接口,提供了数据存储和检索。ArrayList对象的大小是按照存储的数据来动态扩充与收缩的。所以在声明ArrayList对象时并不需要指定它的长度。
    1. ArrayList list1 = new ArrayList();  
    2.   
    3. //新增数据  
    4. list1.Add("cde");  
    5. list1.Add(5678);  
    6.   
    7. //修改数据  
    8. list[2] = 34;  
    9.   
    10. //移除数据  
    11. list.RemoveAt(0);  
    12.   
    13. //插入数据  
    14. list.Insert(0, "qwe");  
    ArrayList list1 = new ArrayList();
    
    //新增数据
    list1.Add("cde");
    list1.Add(5678);
    
    //修改数据
    list[2] = 34;
    
    //移除数据
    list.RemoveAt(0);
    
    //插入数据
    list.Insert(0, "qwe");
    
           从上面的例子看,ArrayList好像解决了数组中所有的缺点,为什么又会有List?
           我们从上面的例子看,在List中,我们不仅插入了字符串cde,而且插入了数字5678。这样在ArrayList中插入不同类型的数据是允许的。因为ArrayList会把插入其中的数据当object类型来处理,在我们使用ArrayList处理数据时,很可能会报类型不匹配的错误,也就是ArrayList不是类型安全的。在存储或检索值类型时通常发生装箱和取消装箱的操作,带来很大的性能损耗。
           装箱与拆箱的概念:
           简单的说:
           装箱:就是将值类型的数据打包到引用类型的实例中
           比如将string类型的值赋值abc赋给object对象obj
    1. String  i=”abc”;  
    2. object obj=(object)i;  
    String  i=”abc”;
    object obj=(object)i;
    
           拆箱:就是从引用数据中提取值类型
           比如将object对象obj的值赋值给string类型的变量i
    1. object obj=”abc”;  
    2. string i=(string)obj;  
    object obj=”abc”;
    string i=(string)obj;
    
           装箱与拆箱的操作是非常耗性能的。

    泛型List

           因为ArrayList存在不安全类型与装箱拆箱的缺点,所以出现了泛型的概念。List类是ArrayList类的泛型等效类,它的大部分用法都与ArrayList相似,因为List类也继承了IList接口。最关键的区别在于,在声明List集合时,我们同时需要为其声明List集合内的对象类型。
    1. List<string> list = new List<string>();  
    2.   
    3. //新增数据  
    4. list.Add(“abc”);  
    5.   
    6. //修改数据  
    7. list[0] = “def”;  
    8.   
    9. //移除数据  
    10. list.RemoveAt(0);  
    List<string> list = new List<string>();
    
    //新增数据
    list.Add(“abc”);
    
    //修改数据
    list[0] = “def”;
    
    //移除数据
    list.RemoveAt(0);
    
    上例中如果我们往List集合中插入int数组123,IDE就会报错,且不能通过编译。这样就避免了前面讲的类型安全问题与装箱拆箱的性能问题了。

    总结

          数组的容量是固定的,只能一次获取或设置一个元素的值,而ArrayList或List<T>的容量可根据需要自动扩充、修改、删除、或插入数据。
          数组可以具有多个维度,而ArrayhuoList<T>始终只有一个维度。但是,可以轻松的创建数组列表或列表的列表。特定类型(Object除外)的数组的性能优于ArrayList的性能。这事因为ArrayList的元素属于Object类型;所以在存储或检索值类型时通常发生装箱和拆箱的操作。不过,在不需要重新分配时(即最初容量十分接近列表的最大容量),List<T>的性能与同类型的数组十分相近。
          在决定使用List<T>还是使用ArrayList类(两者具有相似的功能)时,记住List<T>类在大多数情况下执行的更好并且是类型安全的。如果对List<T>类的类型T使用引用类型,则两个类的行为是完全相同的。但是,如果对类型T使用值类型,则需要考虑实现和装箱的问题。
     

    出处:https://blog.csdn.net/finish_dream/article/details/51627904

    ==================================================

      IList, ICollection ,IEnumerable 很显然,这些都是集合接口的定义,先看看定义:

        // 摘要:
        //     表示可按照索引单独访问的对象的非泛型集合。
        [ComVisible(true)]
        public interface IList : ICollection, IEnumerable
        {
            // 摘要:
            //     获取一个值,该值指示 System.Collections.IList 是否具有固定大小。
            //
            // 返回结果:
            //     如果 System.Collections.IList 具有固定大小,则为 true;否则为 false。
            bool IsFixedSize { get; }
            //
            // 摘要:
            //     获取一个值,该值指示 System.Collections.IList 是否为只读。
            //
            // 返回结果:
            //     如果 System.Collections.IList 为只读,则为 true;否则为 false。
            bool IsReadOnly { get; }
    
            // 摘要:
            //     获取或设置指定索引处的元素。
            //
            // 参数:
            //   index:
            //     要获得或设置的元素从零开始的索引。
            //
            // 返回结果:
            //     指定索引处的元素。
            //
            // 异常:
            //   System.ArgumentOutOfRangeException:
            //     index 不是 System.Collections.IList 中的有效索引。
            //
            //   System.NotSupportedException:
            //     设置该属性,而且 System.Collections.IList 为只读。
            object this[int index] { get; set; }
    
            // 摘要:
            //     向 System.Collections.IList 中添加项。
            //
            // 参数:
            //   value:
            //     要添加到 System.Collections.IList 的对象。
            //
            // 返回结果:
            //     新元素所插入到的位置,或为 -1 以指示未将该项插入到集合中。
            //
            // 异常:
            //   System.NotSupportedException:
            //     System.Collections.IList 是只读的。- 或 -System.Collections.IList 具有固定大小。
            int Add(object value);
            //
            // 摘要:
            //     从 System.Collections.IList 中移除所有项。
            //
            // 异常:
            //   System.NotSupportedException:
            //     System.Collections.IList 是只读的。
            void Clear();
            //
            // 摘要:
            //     确定 System.Collections.IList 是否包含特定值。
            //
            // 参数:
            //   value:
            //     要在 System.Collections.IList 中查找的对象。
            //
            // 返回结果:
            //     如果在 System.Collections.IList 中找到 System.Object,则为 true;否则为 false。
            bool Contains(object value);
            //
            // 摘要:
            //     确定 System.Collections.IList 中特定项的索引。
            //
            // 参数:
            //   value:
            //     要在 System.Collections.IList 中查找的对象。
            //
            // 返回结果:
            //     如果在列表中找到 value,则为该项的索引;否则为 -1。
            int IndexOf(object value);
            //
            // 摘要:
            //     在 System.Collections.IList 中的指定索引处插入项。
            //
            // 参数:
            //   index:
            //     从零开始的索引,应在该位置插入 value。
            //
            //   value:
            //     要插入到 System.Collections.IList 中的对象。
            //
            // 异常:
            //   System.ArgumentOutOfRangeException:
            //     index 不是 System.Collections.IList 中的有效索引。
            //
            //   System.NotSupportedException:
            //     System.Collections.IList 是只读的。- 或 -System.Collections.IList 具有固定大小。
            //
            //   System.NullReferenceException:
            //     value 在 System.Collections.IList 中是 null 引用。
            void Insert(int index, object value);
            //
            // 摘要:
            //     从 System.Collections.IList 中移除特定对象的第一个匹配项。
            //
            // 参数:
            //   value:
            //     要从 System.Collections.IList 中移除的对象。
            //
            // 异常:
            //   System.NotSupportedException:
            //     System.Collections.IList 是只读的。- 或 -System.Collections.IList 具有固定大小。
            void Remove(object value);
            //
            // 摘要:
            //     移除指定索引处的 System.Collections.IList 项。
            //
            // 参数:
            //   index:
            //     从零开始的索引(属于要移除的项)。
            //
            // 异常:
            //   System.ArgumentOutOfRangeException:
            //     index 不是 System.Collections.IList 中的有效索引。
            //
            //   System.NotSupportedException:
            //     System.Collections.IList 是只读的。- 或 -System.Collections.IList 具有固定大小。
            void RemoveAt(int index);
        }
    View Code
        // 摘要:
        //     定义所有非泛型集合的大小、枚举器和同步方法。
        [ComVisible(true)]
        public interface ICollection : IEnumerable
        {
            // 摘要:
            //     获取 System.Collections.ICollection 中包含的元素数。
            //
            // 返回结果:
            //     System.Collections.ICollection 中包含的元素数。
            int Count { get; }
            //
            // 摘要:
            //     获取一个值,该值指示是否同步对 System.Collections.ICollection 的访问(线程安全)。
            //
            // 返回结果:
            //     如果对 System.Collections.ICollection 的访问是同步的(线程安全),则为 true;否则为 false。
            bool IsSynchronized { get; }
            //
            // 摘要:
            //     获取一个可用于同步对 System.Collections.ICollection 的访问的对象。
            //
            // 返回结果:
            //     可用于同步对 System.Collections.ICollection 的访问的对象。
            object SyncRoot { get; }
    
            // 摘要:
            //     从特定的 System.Array 索引处开始,将 System.Collections.ICollection 的元素复制到一个 System.Array
            //     中。
            //
            // 参数:
            //   array:
            //     作为从 System.Collections.ICollection 复制的元素的目标位置的一维 System.Array。System.Array
            //     必须具有从零开始的索引。
            //
            //   index:
            //     array 中从零开始的索引,将在此处开始复制。
            //
            // 异常:
            //   System.ArgumentNullException:
            //     array 为 null。
            //
            //   System.ArgumentOutOfRangeException:
            //     index 小于零。
            //
            //   System.ArgumentException:
            //     array 是多维的。- 或 -源 System.Collections.ICollection 中的元素数目大于从 index 到目标 array
            //     末尾之间的可用空间。
            //
            //   System.ArgumentException:
            //     源 System.Collections.ICollection 的类型无法自动转换为目标 array 的类型。
            void CopyTo(Array array, int index);
        }
    View Code

        // 摘要:
        //     公开枚举器,该枚举器支持在非泛型集合上进行简单迭代。
        [ComVisible(true)]
        [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
        public interface IEnumerable
        {
            // 摘要:
            //     返回一个循环访问集合的枚举器。
            //
            // 返回结果:
            //     可用于循环访问集合的 System.Collections.IEnumerator 对象。
            [DispId(-4)]
            IEnumerator GetEnumerator();
        }
    View Code

     可以看出,所有集合接口的祖宗是IEnumerable

         此接口只有一个方法 GetEnumerator()。是为了实现迭代器模式设计的接口。所有继承了IEnumerable的类,要使用foreach迭代器时,就需要使用该方法。因此也只有实现了该接口的类才可以使用foreach。


         ICollection继承自IEnumerable,IList继承自ICollection

         这两个接口都是为了给集合提供一些公用的方法。只是分了两个层次,IList比ICollection多几个方法,增加,移除成员。可以简单理解为:ICollection主要针对静态集合;IList主要针对动态集合。

          IList 是 ICollection 接口的子代,并且是所有非泛型列表的基接口。IList 实现有三种类别:只读、固定大小和可变大小。无法修改只读 IList。固定大小的 IList 不允许添加或移除元素,但允许修改现有元素。可变大小的 IList 允许添加、移除和修改元素 (IList中的 IsFixedSize { get; }  和  bool IsReadOnly { get; })


      IList,ICollection,IEnumerable 在命名空间System.Collections中。

          关于System.Collections空间

          System.Collections命名空间包含可使用的集合类和相关的接口,提供了集合的基本功能。     

       该命名空间下的.NET非泛型集合类如下所示:

          — System.Collections.ArrayList:数组集合类,使用大小可按动态增加的数组实现Ilist接口。 
          — System.Collections.BitArray:布尔集合类,管理位值的压缩数组,该值为布尔值。
          — System.Collections.Queue:队列,表示对象的先进先出集合。
          — System.Collections.Stack:堆栈,表示对象的简单的后进先出集合。
          — System.Collections.Hashtable:哈希表,表示键/值对的集合,这些键/值对根据键的哈希代码进行组织
          — System.Collections.SortedList:排序集合类,表示键/值对的集合,这些键和值按键排序并可按键和索引访问。

        该命名空间下的.NET非泛型接口如下所示:

          — System.Collections.ICollection:(继承于IEnumerable)定义所有集合的大小,枚举器和同步方法,可以获取集合中项的个数,并能把项复制到一个简单的数组类型中。
          — System.Collections.IComparer:比较两个对象的方法
          — System.Collections.IList:(继承于IEnumerable 和 ICollection)表示可按照索引单独访问一组对象,提供集合的项列表,并可以访问这些项。
          — System.Collections.IDictionary:(继承于IEnumerable 和 ICollection)表示键/值对的集合
          — System.Collections.IDictionaryEnumerator:枚举字典的元素
          — System.Collections.IEnumerator:支持在集合上进行简单迭代,可以迭代集合中的项。支持在非泛型集合进行简单迭代。


      IList<T>,ICollection<T>,IEnumerable<T> 在System.Collections.Generic 命名空间中。     

                    System.Collections.Generic是.net中的泛型集合 

        IList<T>,ICollection<T>,IEnumerable<T> 是2.0引入泛型以后新增的。主要是提高重用性与类型安全。
      IEnumerable<T>继承自IEnumerable,ICollection<T>继承自IEnumerable<T>,List<T>继承自ICollection<T>
      因此可以完全使用泛型接口,而放弃使用ICollection和IList。泛型接口提供了更好的类型安全和编译时的检验。
          补充:  IEnumerable<T>和IEnumerable都只有一个方法。ICollection<T>和ICollection的结构是不一样的。ICollection<T>比ICollection多几个方法。它包含了几个IList中的几个方法。也许是对以前的改进。

     

        IEnumerable 和 IEnumerator

     IEnumerator

          如果一个类实现了IEnumerator,也就是实现Current属性,MoveNext方法,Reset方法。只要实现这些方法,这个类就可以用foreach这种语法了。 

          IEnumerable接口主要实现了GetEnumerator方法,该方法返回一个IEnumerator。一个类实现IEnumerable接口后,调用foreach语法的时候,会自动的调用GetEnumerator方法,然后在这个IEnumerator中遍历。  所以只要实现两者之中任意一个接口,就可以用foreach语法了。但是本质上都是对IEnumerator做foreach,只是一个是直接,一个是间接。

          代码说明:

      比如类Test,实现了IEnumerable,那么下面的代码

        foreach (Test  t  in ts)

        {     ... } 

      说明代码就功能上等同于下面的代码

        IEnumerator td= ts.GetEnumerator(); 

        while (td.MoveNext()) 

        {     

          t = (Foo)td.Current()    

          ...  

        }   

        如果一个类,同时实现了IEnumerator<T>,IEnumerable<T>,那么就是糟糕的设计 因为用foreach语法的时候,会先调用IEnumerable的GetEnumerator方法。

     

     

      IList<T> 和List<T>

      首先IList 泛型接口是 ICollection 泛型接口的子代,并且是所有泛型列表的基接口。
      它仅仅是所有泛型类型的接口,并没有太多方法可以方便实用,如果仅仅是作为集合数据的承载体,确实,IList可以胜任。
      不过,更多的时候,我们要对集合数据进行处理,从中筛选数据或者排序。这个时候IList就爱莫能助了。
      1、当你只想使用接口的方法时,ILis<>这种方式比较好.他不获取实现这个接口的类的其他方法和字段,有效的节省空间.(既然子类是继承父类的子类又有自己的属性和方法,那么子类NEW出来后这些都应该有而且必须有的,不论放在父类的变量里面还是自身类型的变量里面,不然的话向上转型后再向下转型数据就会丢失喽,太可怕了!)
      2、IList <>是个接口,定义了一些操作方法这些方法要你自己去实现,List <>是泛型类,它已经实现了IList <>定义的那些方法
      IList ilist=new List ();
      List list=new List ();
      这两行代码,从操作上来看,实际上都是创建了一个List对象的实例,也就是说,他们的操作没有区别。
      只是用于保存这个操作的返回值变量类型不一样而已。
      那么,我们可以这么理解,这两行代码的目的不一样。
      List List11 =new List ();
      是想创建一个List,而且需要使用到List的功能,进行相关操作。
      而IList IList11 =new List ();
      只是想创建一个基于接口IList的对象的实例,只是这个接口是由List实现的。所以它只是希望使用到IList接口规定的功能而已。

     

      如果一个方法的返回值是IEnumerable<T> ,必须在方法后面使用.ToList()方法才能得到一个集合数据

         List<XElement> grandchildElements = xlsElement.XPathSelectElements("//model").ToList();

      使用.ToArray()方法,就会创建一个数组数据

        XElement[] elements = xlsElement.Descendants(nodeName).ToArray();

      集合数据要用foreach来遍历,而数组数据可以使用下标操作。

     

    出处:https://blog.csdn.net/superhoy/article/details/20908739

    ==========================================================================

    楼主最近看了下

    IQueryable 和 IEnumerable

    的区别。

    当真被忽悠的死去活来。。。

    网上都说 IQueryable 和 IEnumerable区别很大,然后怎么着怎么着。。。可怜

    然后我就去测试了啊

    先拿出我的数据库表结构。

    这里是我的查询语句。比较简单

    1. TestDataEntities db = new TestDataEntities();  
    2.             IQueryable<Orders> q = db.Orders.OrderBy(x=>x.id).Skip(1).Take(2);  
    3.             IEnumerable<Orders> e = db.Orders.OrderBy(x=>x.id).Skip(1).Take(2);  
    4.   
    5.             Console.WriteLine("IQueryable :  "+q.ToString());  
    6.             Console.WriteLine("---------------------------------------------------------");  
    7.             Console.WriteLine("IEnumerable :  " + e.ToString());  
    TestDataEntities db = new TestDataEntities();
                IQueryable<Orders> q = db.Orders.OrderBy(x=>x.id).Skip(1).Take(2);
                IEnumerable<Orders> e = db.Orders.OrderBy(x=>x.id).Skip(1).Take(2);
    
                Console.WriteLine("IQueryable : 
    "+q.ToString());
                Console.WriteLine("---------------------------------------------------------");
                Console.WriteLine("IEnumerable : 
    " + e.ToString());

    输出结果:

    IQueryable :

    1. SELECT TOP (2)   
    2. [Extent1].[id] AS [id],   
    3. [Extent1].[parentid] AS [parentid],   
    4. [Extent1].[code] AS [code]  
    5. FROM ( SELECT [Extent1].[id] AS [id], [Extent1].[parentid] AS [parentid], [Extent1].[code] AS [code], row_number() OVER (ORDER BY [Extent1].[id] ASCAS [row_number]  
    6.     FROM [dbo].[Orders] AS [Extent1]  
    7. )  AS [Extent1]  
    8. WHERE [Extent1].[row_number] > 1  
    9. ORDER BY [Extent1].[id] ASC  
    SELECT TOP (2) 
    [Extent1].[id] AS [id], 
    [Extent1].[parentid] AS [parentid], 
    [Extent1].[code] AS [code]
    FROM ( SELECT [Extent1].[id] AS [id], [Extent1].[parentid] AS [parentid], [Extent1].[code] AS [code], row_number() OVER (ORDER BY [Extent1].[id] ASC) AS [row_number]
    	FROM [dbo].[Orders] AS [Extent1]
    )  AS [Extent1]
    WHERE [Extent1].[row_number] > 1
    ORDER BY [Extent1].[id] ASC

    
    
    

    IEnumerable :

    1. SELECT TOP (2)   
    2. [Extent1].[id] AS [id],   
    3. [Extent1].[parentid] AS [parentid],   
    4. [Extent1].[code] AS [code]  
    5. FROM ( SELECT [Extent1].[id] AS [id], [Extent1].[parentid] AS [parentid], [Extent1].[code] AS [code], row_number() OVER (ORDER BY [Extent1].[id] ASCAS [row_number]  
    6.     FROM [dbo].[Orders] AS [Extent1]  
    7. )  AS [Extent1]  
    8. WHERE [Extent1].[row_number] > 1  
    9. ORDER BY [Extent1].[id] ASC  
    SELECT TOP (2) 
    [Extent1].[id] AS [id], 
    [Extent1].[parentid] AS [parentid], 
    [Extent1].[code] AS [code]
    FROM ( SELECT [Extent1].[id] AS [id], [Extent1].[parentid] AS [parentid], [Extent1].[code] AS [code], row_number() OVER (ORDER BY [Extent1].[id] ASC) AS [row_number]
    	FROM [dbo].[Orders] AS [Extent1]
    )  AS [Extent1]
    WHERE [Extent1].[row_number] > 1
    ORDER BY [Extent1].[id] ASC

    有区别吗?没有哇!!!

    后来楼主就较真了!!!!!!是的,较真了!!!为何网上这么多人说有区别!发火发火发火发火

    然后发现。。。。是这个原因!~

    看楼下代码

    1. TestDataEntities db = new TestDataEntities();  
    2.             IQueryable<Orders> q = db.Orders.OrderBy(x => x.id).AsQueryable<Orders>().Skip(10).Take(2);  
    3.             IEnumerable<Orders> e = db.Orders.OrderBy(x => x.id).AsEnumerable<Orders>().Skip(10).Take(2);  
    4.   
    5.             foreach (var item in q)  
    6.             {  
    7.                 Console.WriteLine("123");  
    8.             }  
    9.   
    10.             foreach (var item in e)  
    11.             {  
    12.                 Console.WriteLine("234");  
    13.             }  
    TestDataEntities db = new TestDataEntities();
                IQueryable<Orders> q = db.Orders.OrderBy(x => x.id).AsQueryable<Orders>().Skip(10).Take(2);
                IEnumerable<Orders> e = db.Orders.OrderBy(x => x.id).AsEnumerable<Orders>().Skip(10).Take(2);
    
                foreach (var item in q)
                {
                    Console.WriteLine("123");
                }
    
                foreach (var item in e)
                {
                    Console.WriteLine("234");
                }

    原因其实出在

    AsQueryable 和 AsEnumerable  

    反正就是加载方式不同

    上面代码的sql语句是这样的!

    IQueryable :

    1. SELECT TOP (2)   
    2. [Extent1].[id] AS [id],   
    3. [Extent1].[parentid] AS [parentid],   
    4. [Extent1].[code] AS [code]  
    5. FROM ( SELECT [Extent1].[id] AS [id], [Extent1].[parentid] AS [parentid], [Extent1].[code] AS [code], row_number() OVER (ORDER BY [Extent1].[id] ASCAS [row_number]  
    6. FROM [dbo].[Orders] AS [Extent1]  
    7. )  AS [Extent1]  
    8. WHERE [Extent1].[row_number] > 10  
    9. ORDER BY [Extent1].[id] ASC  
    SELECT TOP (2) 
    [Extent1].[id] AS [id], 
    [Extent1].[parentid] AS [parentid], 
    [Extent1].[code] AS [code]
    FROM ( SELECT [Extent1].[id] AS [id], [Extent1].[parentid] AS [parentid], [Extent1].[code] AS [code], row_number() OVER (ORDER BY [Extent1].[id] ASC) AS [row_number]
    FROM [dbo].[Orders] AS [Extent1]
    )  AS [Extent1]
    WHERE [Extent1].[row_number] > 10
    ORDER BY [Extent1].[id] ASC

    
    
    

    IEnumerable :

    1. SELECT   
    2. [Extent1].[id] AS [id],   
    3. [Extent1].[parentid] AS [parentid],   
    4. [Extent1].[code] AS [code]  
    5. FROM [dbo].[Orders] AS [Extent1]  
    6. ORDER BY [Extent1].[id] ASC  
    SELECT 
    [Extent1].[id] AS [id], 
    [Extent1].[parentid] AS [parentid], 
    [Extent1].[code] AS [code]
    FROM [dbo].[Orders] AS [Extent1]
    ORDER BY [Extent1].[id] ASC
    是的,你没看错,奇怪在于IEnumerable生成的语句,是查询全表。

    聪明的你肯定会联想到。IEnumerable是通过缓存全表,然后才分页查找的!!!所以IEnumerable性能不好!

    为什么????!!!!

    因为:

    IQueryable     是 linq to sql           这家伙操作数据库

    IEnumerable 是  linq to object     这家伙操作内存

    区别在这里!

    当然网上还有说IQueryable 和 IEnumerable其他区别(这个楼主没有验证)

    IEnumerable<T>查询必须在本地执行.并且执行查询前我们必须把所有的数据加载到本地

     

    总结一下:

    IQueryable     是 linq to sql         这家伙操作数据库

    IEnumerable 是  linq to object     这家伙操作内存

    IEnumerable 会查询全部数据,然后在内存里进行分页或者筛选操作。

    但是真正导致他们使用哪种方式的,是AsQueryable() 和 AsEnumerable()  !!!!!

    出处:https://blog.csdn.net/hanjun0612/article/details/50070081

    ===================================================================

  • 相关阅读:
    [bzoj1731] [Usaco2005 dec]Layout 排队布局
    [bzoj1914] [Usaco2010 OPen]Triangle Counting 数三角形
    [bzoj1774] [Usaco2009 Dec]Toll 过路费
    [bzoj1783] [Usaco2010 Jan]Taking Turns
    [bzoj1705] [Usaco2007 Nov]Telephone Wire 架设电话线
    [bzoj1700]: [Usaco2007 Jan]Problem Solving 解题
    定时启动任务
    数据库表转javaBean
    验证码的生成
    MD5加密与验证
  • 原文地址:https://www.cnblogs.com/mq0036/p/9189427.html
Copyright © 2011-2022 走看看