zoukankan      html  css  js  c++  java
  • C#中的 IList, ICollection ,IEnumerable 和 IEnumerator

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

     1 // 摘要:
     2     //     表示可按照索引单独访问的对象的非泛型集合。
     3     [ComVisible(true)]
     4     public interface IList : ICollection, IEnumerable
     5     {
     6         
     7         bool IsFixedSize { get; }
     8         
     9         bool IsReadOnly { get; }
    10        
    11         object this[int index] { get; set; }
    12         
    13         int Add(object value);
    14         
    15         void Clear();
    16         
    17         bool Contains(object value);
    18         
    19         int IndexOf(object value);
    20         
    21         void Insert(int index, object value);
    22         
    23         void Remove(object value);
    24         
    25         void RemoveAt(int index);
    26     }
    IList
     1 // 摘要:
     2     //     定义所有非泛型集合的大小、枚举数和同步方法。
     3     [ComVisible(true)]
     4     public interface ICollection : IEnumerable
     5     {        
     6         int Count { get; }
     7         
     8         bool IsSynchronized { get; }
     9         
    10         object SyncRoot { get; }
    11 
    12           void CopyTo(Array array, int index);
    13     }
    ICollection
     1 // 摘要:
     2     //     公开枚举数,该枚举数支持在非泛型集合上进行简单迭代。
     3     [ComVisible(true)]
     4     [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
     5     public interface IEnumerable
     6     {
     7         // 摘要:
     8         //     返回一个循环访问集合的枚举数。
     9         //
    10         // 返回结果:
    11         //     一个可用于循环访问集合的 System.Collections.IEnumerator 对象。
    12         [DispId(-4)]
    13         IEnumerator GetEnumerator();
    14     }
    IEnumerable

         可以看出,所有集合接口的祖宗是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

     1     // 摘要:
     2     //     支持对非泛型集合的简单迭代。
     3     [ComVisible(true)]
     4     [Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")]
     5     public interface IEnumerator
     6     {
     7         // 摘要:
     8         //     获取集合中的当前元素。
     9         //
    10         // 返回结果:
    11         //     集合中的当前元素。
    12         object Current { get; }
    13 
    14         // 摘要:
    15         //     将枚举数推进到集合的下一个元素。
    16         //
    17         // 返回结果:
    18         //     如果枚举数成功地推进到下一个元素,则为 true;如果枚举数越过集合的结尾,则为 false。
    19         //
    20         // 异常:
    21         //   System.InvalidOperationException:
    22         //     在创建了枚举数后集合被修改了。
    23         bool MoveNext();
    24         //
    25         // 摘要:
    26         //     将枚举数设置为其初始位置,该位置位于集合中第一个元素之前。
    27         //
    28         // 异常:
    29         //   System.InvalidOperationException:
    30         //     在创建了枚举数后集合被修改了。
    31         void Reset();
    32     }
    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来遍历,而数组数据可以使用下标操作。

  • 相关阅读:
    加强面向对象设计思想需要学习的知识
    (转载)myeclipse快捷键
    tomcat的jdbc驱动
    mysql常见设置
    不用配制数据源如何用JDBC连接access数据库
    关于updatePanel
    jsp常见问题
    Servlet问题
    Rational Rose未找到suite objects.dll问题
    jsp+servlet+javabean实现简单的查询
  • 原文地址:https://www.cnblogs.com/tech-bird/p/3462769.html
Copyright © 2011-2022 走看看