C#中可枚举类型详解

2019-12-30 18:12:21刘景俊

下面来延时如何使用枚举类型:


//下面来看枚举类型的使用
      SimpleCollection collection = new SimpleCollection(new object[]{1,2,3,4,5});

      //使用方法
      //接口 变量名=继承了该接口的类的实例
      IEnumerator enumrator = collection.GetEnumerator();

      while(enumrator.MoveNext())
      {
        
        Console.WriteLine(enumrator.Current);
      }
      Console.ReadKey();


 SimpleCollection simple = new SimpleCollection(new object[] { 1, 2, 3, 4, 5, 6 });
      IEnumerator enumerator = simple.GetEnumerator();
      while(enumerator.MoveNext())
      {
        Console.WriteLine(enumerator.Current);
      }
      //最重要的是,实现了那两个接口,我们就可以对我们的集合使用foreach迭代了,看下面
      foreach(var s in simple)
      {
        Console.WriteLine(s);
      }

下面给出两个接口的泛型实现:

首先需要注意的是:

1.IEnumerable<T>接口继承自IEnumerable      两者具有相同接口,所以必须实现泛型和非泛型版本的GetEumerator方法

2.IEnumerator<T>接口继承自IEnumerator和IDisposable  需要多实现泛型和非泛型版本的Current属性和IDisposable接口的Dispose方法。

代码如下:

 


////下面创建一个可枚举的泛类型
  //首先该类型必须要继承IEnumerable<T>接口
  //因为IEnumerable<T>接口继承IEnumerable接口 所以必须同时实现泛型和非泛型的GetEnumerator方法
  public class SimpleCollection<T> : IEnumerable<T>
  {
    private T[] array;
    public SimpleCollection(T[] items)
    {
      array = items;
     
    }
    //实现IEnumerable<T>接口的GetNumerator方法 该方法返回一个继承IEnumerator接口的类的实例
    public IEnumerator<T> GetEnumerator()
    {
      return new Enumerator<T>(array);//这步需要重视
    }
    //为了避免混淆 在此显式实现非泛型的接口
    IEnumerator IEnumerable.GetEnumerator()
    {
      return new Enumerator<T>(array);//这步需要重视
    }

    //定义一个嵌套类来继承IEnumerator<T>的接口
    //IEnumerator<T>接口继承自IDisposable和IEnumerator接口
    //该接口的唯一成员是Current属性 但是同时也要实现其非泛型版本!!!
    //另外还需要实现IDisposable的Dispose方法和IEnumerator的两个方法
    public class Enumerator<_T> : IEnumerator<_T>
    {
      private int flag;
      private _T[] elements = null;
      public Enumerator(_T[] items)
      {
        elements = items;
        flag = -1;
      }
      //实现IEnumerator<T>接口的Current属性; 此属性返回集合的当前元素,是只读的
      public _T Current
      {
        get
        {
          if (flag > elements.Length - 1) throw new InvalidOperationException("枚举已经结束");
          else if (flag < 0) throw new InvalidOperationException("枚举尚未开始");
          else return elements[flag];
        }
      }
      //为了避免混淆  显示实现IEnumerator接口的Current属性
      object IEnumerator.Current
      {
        get { return Current; } //直接返回上面的泛型属性 比较经典
      }

      //实现IDisposable接口的Dispose方法 支持确定性垃圾回收 将枚举数的状态设置为after 也就是把标记位设为最大索引+1
      public void Dispose()
      {
        flag = elements.Length + 1;
      }

      //实现IEnumerator接口的MoveNext方法 将枚举移动到下一位
      public bool MoveNext()
      {
        ++flag;
        if (flag > (elements.Length - 1)) return false;
        else return true;
      }
      //实现IEnumerator接口的Reset方法 使枚举回到开头
      public void Reset()
      {
        flag = -1;
      }
    }