亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

C#中可枚舉類型詳解

2019-10-29 21:08:31
字體:
來源:轉載
供稿:網友

枚舉是迭代一個集合中的數據項的過程。

我們經常使用的大多數集合實際上都已經實現了枚舉的接口IEnumerable和IEnumerator接口,這樣才能使用foreach迭代,有些是含有某種抽象了枚舉細節的接口:ArrayList類型有索引,BitArray有Get方法,哈希表和字典有鍵和值..........其實他們都已經實現了IEnumerable和IEnumerator接口。所以一切的集合和數組都可以用IEnumerable或者IEnumerable<T>接口來定義。

 IEnumerable lists1 = new int[] { 3, 4, 5 };      foreach(var val in lists1)      {        Console.WriteLine(val);      }      IEnumerable<int> lists2=new int[]{1,2,3};      foreach(var val in lists2)      {        Console.WriteLine(val);      }

下面講解一下 自己來定義可枚舉類型(簡單說就是自己定義的 ,可以進行foreach迭代的集合):

因為枚舉非常有好處,可以消除很多的錯誤,所以實現某種標準是有好處的。這種標準就是IEnumerable和IEnumerator接口,必須實現了它才能夠使用foreach迭代,才能真正算是一個自己定義的,功能健全的集合。

我們自己建立的可枚舉類型必須實現IEnumerable和IEnumerator接口(其實兩者都有一個泛型實現)。

IEnumerable接口含有一個方法,該方法返回一個枚舉器對象,枚舉器對象實現了IEnumerator接口(實際上可以認為繼承和實現了IEnumerator的接口的類的對象就是枚舉器對象),可以用它來進行迭代。

下面是兩個接口的定義(系統早已經定義好):

 public interface IEnumerable  {    IEnumerator GetEnumerator();  }

該接口只有一個GetEnumerator的方法,返回一個枚舉器,用于枚舉集合中的元素。 

 public interface IEnumerator  {    object Current { get; };//Current屬性返回集合的當前元素    bool MoveNext();    //將枚舉移動到下一位    void Reset();     //使枚舉回到開頭  }

凡是繼承和實現了上面這個接口的類對象就是枚舉器,可以利用上面的三個方法進行枚舉,非常安全。不過需要自己在繼承了接口的代碼中去寫實現過程。

一般的情況是:枚舉器是枚舉模式的一部分,通常被實現為枚舉類型(繼承IEnumerable)的一個嵌套類(繼承IEnumerator)。嵌套類的好處就是可以訪問外部類的私有成員,不破壞封裝的原則。

下面我們自己來定義一個枚舉類型,代碼如下:

public class SimpleCollection :IEnumerable  {    //定義一個數組的字段    private object[] array;    //定義一個構造函數    public SimpleCollection(object []items)    {      array = items;    }    //實現IEnumerable接口的GetNumerator方法 該方法返回一個繼承IEnumerator接口的類的實例    public  IEnumerator GetEnumerator()    {      return  new Enumerator(array);    }    //定義一個嵌套類來繼承IEnumerator的接口    public class Enumerator : IEnumerator    {      //定義一個標記字段      private int flag;      //定義一個數組的字段      private object[] elements = null;      //定義一個構造函數      public Enumerator(object []items)      {        elements = items;        flag = -1; //將標記位初始化                //也可以采用下面的方法        //elements = new object[items.Length];        //Array.Copy(items, elements, items.Length);//此靜態方法用于將一個數組中的元素復制到另外一個數組      }      //實現IEnumerator接口的Current屬性; 此屬性返回集合的當前元素,是只讀的      public object Current      {        get        {          if (flag > elements.Length - 1) throw new InvalidOperationException("枚舉已經結束");          else if (flag < 0) throw new InvalidOperationException("枚舉尚未開始");          else return elements[flag];        }      }      //實現IEnumerator接口的MoveNext方法 將枚舉移動到下一位      public bool MoveNext()      {        ++flag;        if (flag > (elements.Length - 1)) return false;        else return true;      }      //實現IEnumerator接口的Reset方法 使枚舉回到開頭      public void Reset()      {        flag = -1;      }    }

下面來延時如何使用枚舉類型:

//下面來看枚舉類型的使用      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;      }    }

怎么使用呢:

   SimpleCollection<string> colletion = new SimpleCollection<string>(new string[] { "ranran", "Huaran" });      IEnumerator<string> enumorator = colletion.GetEnumerator();      while(enumorator.MoveNext())      {        Console.WriteLine(enumorator.Current);      }      foreach(var v in colletion)      {        Console.WriteLine(v);      }      Console.ReadKey();

還可以直接使用迭代器:
使用迭代器是另一種完全實現上面兩個接口的方案,這是最為簡便和可讀的方法

而且使用迭代器可以很方便和快捷的設置各種枚舉情況 如雙重的迭代 反向的迭代 臨時的集合和負責迭代等等 比上面的實現更為簡單

迭代的關鍵字是yield 需要依靠一個迭代器塊(注意是循環+yield  return,或者 yiled break)

 public class MyCollection:IEnumerable  {    private object[] array;    public MyCollection(object []items)    {      array = items;    }    public IEnumerator GetEnumerator() //實現都可以依靠編譯器去完成    {      //foreach (object v in array)      //{      //  yield return v;      //}      //關鍵字是yield 并不是foreach 我們也可以按照下面這個方法進行實現      for(int i=0;i<array.Length;i++)      {        yield return array[i];      }      //當然其它的while循環也可以。。    }  }//實現:MyCollection collection = new MyCollection(new object[] { 1, 2, 3 });      foreach(var v in collection)      {        Console.WriteLine(v);      }

可以自己設置迭代的情況:

 

   public class MyCollection2:IEnumerable  {     private object[] array;     public MyCollection2(object []items)    {      array = items;    }    //可以在迭代器塊中設置迭代的實現情況 即具體迭代多少個元素    //比如我們只想迭代4個元素    public IEnumerator GetEnumerator()     {       int count = 0;//設計一個標記位      foreach(object item in array)      {        ++count;        yield return item;        if (count == 4) yield break; //break關鍵字 退出迭代 實際上迭代在實現當中就是一個循環 利用break跳出也合情合理      }     }     }////// MyCollection2 collection2 = new MyCollection2(new object[]{4,5,6,7,8});      //它就只會輸出4,5,6,7      foreach (var v in collection2)      {        Console.WriteLine(v);      }

雙重迭代:

 /// <summary>  /// 下面演示雙重迭代 即一次可以迭代兩個集合中的元素  /// </summary>  public class MyColletion3:IEnumerable  {    private object[] List1;    public string[] List2;    public MyColletion3(object []items1,string []items2)    {      this.List1 = items1;      this.List2 = items2;    }    //下面進行雙重迭代    public IEnumerator GetEnumerator()    {      //關鍵代碼      for(int index=0;index<(List1.Length>List2.Length?List2.Length:List1.Length);index++)      {        yield return List1[index];        yield return List2[index];      }    }  }//////// MyColletion3 collection3 = new MyColletion3(new object[] { 1, 2, 3, 5.5 }, new string[] { "RanRan", "Chengdu", "四川" });      foreach(var v in collection3)      {        Console.WriteLine(v);      }      //迭代結果是1 RanRan 2 Chengdu 3 四川

反向迭代:依靠Reverse屬性

  /// <summary>  /// 下面演示反向迭代 說白了就是迭代是從后面開始的 反向迭代器是在Reverse屬性當中實現的  /// </summary>  public class MyColletion4:IEnumerable  {    private object[] items;    public MyColletion4(object []temps)    {      this.items = temps;    }    //一般的正向迭代    public IEnumerator GetEnumerator()    {      for(int index=0;index<items.Length;index++)      {        yield return items[index];      }    }    //實現反向迭代    public IEnumerable Reverse //注意返回IEnumerable對象    {      get      {        for (int index = items.Length - 1; index > -1; index--)        {          yield return items[index];        }      }    }  }//// MyColletion4 collection4 = new MyColletion4(new object[] { 1, 2, 3, 4 });      foreach (var v in collection4)      {        Console.WriteLine(v);      }      //反向迭代      foreach(var v in collection4.Reverse)      {        Console.WriteLine(v);      }      //迭代結果是 4 3 2 1

當然也有一個臨時集合,順便補充一下,迭代和枚舉實現的方案很多,一個返回IEnumerable的方法中加上迭代器塊也是一個迭代集合

具體看下面的代碼

 

 //還有一種最為簡單的迭代 就是一個返回IEnumerable對象的方法 在這方法中寫上迭代器    //在此補充一個臨時集合 關鍵看代碼怎么寫(以枚舉當前月份的日期為列子)    public static IEnumerable GetMonthDate()    {      DateTime dt = DateTime.Now;      int currentMonth = dt.Month;      while(currentMonth==dt.Month)      {        string temp = currentMonth.ToString() + "/" + dt.Day.ToString();        dt = dt.AddDays(1);        yield return temp;      }    }///實現foreach(var v in GetMonthDate())      {        Console.WriteLine(v);      }

這兒 我作為一個新手自己給自己總結一下可枚舉類型和接口的含義:

可枚舉類型(集合&數組等):

              在實際開發當中,可以自己去定義一些與集合差不多的類型,對該類型的元素的訪問,用一般的while,for循環比較不方便,我們需要自己去定義一個枚舉器。

              枚舉類型(繼承IEnumerable接口):包括一個集合元素和一個枚舉器。

              枚舉器是枚舉類型當中的一個嵌套類(繼承了IEnumerator接口):具體實現見上。

              /////// 這樣便可以讓自定義的可枚舉類型實現foreach迭代。

              當然也可以直接利用迭代來實現上面兩個接口。//////

接口:是一種標準,它給出了一種約束和引導,需要我們去寫代碼實現它。雖然看上去多次一舉,不過在后面對類的實例的使用中非常方便。

 以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
麻豆国产精品va在线观看不卡| 91天堂在线视频| 热re91久久精品国99热蜜臀| 国产精品偷伦视频免费观看国产| 亚洲欧美国产日韩中文字幕| 久久久久久久激情视频| 欧美黄色性视频| 深夜精品寂寞黄网站在线观看| 国产视频精品久久久| 精品亚洲一区二区三区在线播放| 亚洲一区二区三区成人在线视频精品| 亚洲a在线观看| 91精品国产乱码久久久久久蜜臀| 国产精品6699| 日韩电影中文字幕在线观看| 欧美激情videoshd| 91免费综合在线| 日韩免费在线免费观看| 欧美性理论片在线观看片免费| 在线播放日韩欧美| 日本一欧美一欧美一亚洲视频| 久久久久国产精品免费| 日韩精品久久久久久福利| 性夜试看影院91社区| 日韩欧美在线中文字幕| 亚洲欧美中文在线视频| 成人免费观看a| 日本精品一区二区三区在线播放视频| 尤物九九久久国产精品的分类| 国产精品成人免费视频| 日韩在线欧美在线国产在线| 亚洲大胆人体av| 欧美激情a在线| 不卡毛片在线看| 日韩最新在线视频| 中文在线资源观看视频网站免费不卡| 欧美巨猛xxxx猛交黑人97人| 91av视频在线| 亚洲性视频网站| 91九色在线视频| 91精品国产91久久久| 亚洲天堂开心观看| 国产欧美欧洲在线观看| 亚洲一区二区三区成人在线视频精品| 亚洲在线一区二区| 欧美中文在线免费| 亚洲精品美女在线观看播放| 国产精品久久久久久久久久免费| 欧美视频在线看| 国产精品99久久久久久人| 国产精品高潮呻吟久久av黑人| 午夜精品www| 日韩欧美aaa| 国产美女精彩久久| 亚洲日本欧美日韩高观看| 久久99精品久久久久久噜噜| 欧美成年人视频网站欧美| 欧美美最猛性xxxxxx| 欧美国产在线电影| 日韩色av导航| 国产亚洲精品高潮| 日韩中文字幕精品视频| 亚洲精品女av网站| 久久久久久久久久久国产| 91高清视频免费观看| 国产精品久久久久久久久久| 亚洲欧美第一页| 日韩在线视频观看正片免费网站| 一本色道久久88综合日韩精品| 久久久久久久久久国产| 欧美成人在线网站| 欧美日韩中文字幕在线| 国产精品亚洲视频在线观看| 久久久久女教师免费一区| 国产视频自拍一区| 亚洲精品一区二区在线| 最新69国产成人精品视频免费| 91精品视频一区| 久久精品2019中文字幕| 国产91色在线| 日韩av色在线| 欧美精品福利在线| 亚洲国产女人aaa毛片在线| 欧美亚洲另类激情另类| 国产精品久久不能| 日韩精品在线播放| 清纯唯美日韩制服另类| 日本高清视频精品| 精品国偷自产在线视频99| 日韩不卡中文字幕| 国产精品免费电影| 国产精品视频导航| 综合激情国产一区| 欧美xxxx做受欧美.88| 欧美华人在线视频| 丝袜亚洲另类欧美重口| 精品成人久久av| 欧美性猛交xxxx偷拍洗澡| 好吊成人免视频| 91chinesevideo永久地址| 国产成人精品av在线| 亚洲成人精品av| 欧美综合国产精品久久丁香| 亚洲香蕉伊综合在人在线视看| 国产精品久久久久久久久久尿| 久久综合伊人77777蜜臀| 亚洲精品理论电影| 尤物九九久久国产精品的分类| 97国产真实伦对白精彩视频8| 国产精品丝袜高跟| 久久久电影免费观看完整版| 国产美女久久精品| 欧美一区二区三区免费观看| 日韩a**站在线观看| 2019亚洲日韩新视频| 7m精品福利视频导航| 日韩中文av在线| 日本中文字幕不卡免费| 国产精品久久精品| 久久精品国产亚洲精品2020| 国产精品久久77777| 成人性教育视频在线观看| 亚洲国产免费av| 中国china体内裑精亚洲片| 91精品国产综合久久香蕉的用户体验| 欧美激情精品久久久久久黑人| 欧美精品日韩www.p站| 亚洲综合视频1区| 亚洲欧美日本伦理| 三级精品视频久久久久| 人人爽久久涩噜噜噜网站| 欧美精品在线免费观看| 这里只有精品视频| 成人久久久久久| 久久精品国产视频| 一本色道久久88综合亚洲精品ⅰ| 欧美国产日韩视频| 欧美丰满少妇xxxx| 2019中文字幕在线免费观看| 日韩精品视频免费在线观看| 91精品视频在线播放| 欧美黑人一区二区三区| 欧美精品国产精品日韩精品| 亚洲美女视频网| 日韩一区二区在线视频| 欧美在线视频免费观看| 一区二区国产精品视频| 欧美精品18videosex性欧美| 国产精品2018| 欧美日韩另类字幕中文| 亚洲成人激情视频| 国产一区二区三区欧美| 成人在线激情视频| 在线视频精品一| 亚洲美女性视频| 亚洲电影免费观看| 精品久久久久久久中文字幕| 91久久精品国产| 日本久久精品视频| 日韩视频在线观看免费| 精品亚洲一区二区三区在线播放| 日韩中文字幕视频在线观看| 久久免费视频网站| 57pao国产精品一区|