国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C# - C#中可枚舉類型詳解

C#中可枚舉類型詳解

2022-01-24 13:41華然 C#

這篇文章主要介紹了C#中可枚舉類型,IEnumerable和IEnumerator接口j及其泛型實現和迭代器,具有一定的參考價值,感興趣的小伙伴們可以參考一下

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

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

?
1
2
3
4
5
6
7
8
9
10
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的接口的類的對象就是枚舉器對象),可以用它來進行迭代。

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

?
1
2
3
4
public interface IEnumerable
 {
   IEnumerator GetEnumerator();
 }

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

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

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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;
      }
    }

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
//下面來看枚舉類型的使用
      SimpleCollection collection = new SimpleCollection(new object[]{1,2,3,4,5});
 
      //使用方法
      //接口 變量名=繼承了該接口的類的實例
      IEnumerator enumrator = collection.GetEnumerator();
 
      while(enumrator.MoveNext())
      {
        
        Console.WriteLine(enumrator.Current);
      }
      Console.ReadKey();
?
1
2
3
4
5
6
7
8
9
10
11
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方法。

代碼如下:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
////下面創建一個可枚舉的泛類型
  //首先該類型必須要繼承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;
      }
    }

怎么使用呢:

?
1
2
3
4
5
6
7
8
9
10
11
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)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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);
      }

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

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   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);
      }

雙重迭代:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/// <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屬性

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
  /// <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的方法中加上迭代器塊也是一個迭代集合

具體看下面的代碼

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//還有一種最為簡單的迭代 就是一個返回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迭代。

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

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

 以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/Huaran1chendu/p/4838536.html

延伸 · 閱讀

精彩推薦
  • C#C#實現XML文件讀取

    C#實現XML文件讀取

    這篇文章主要為大家詳細介紹了C#實現XML文件讀取的相關代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    Just_for_Myself6702022-02-22
  • C#C#通過KD樹進行距離最近點的查找

    C#通過KD樹進行距離最近點的查找

    這篇文章主要為大家詳細介紹了C#通過KD樹進行距離最近點的查找,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    帆帆帆6112022-01-22
  • C#C#裁剪,縮放,清晰度,水印處理操作示例

    C#裁剪,縮放,清晰度,水印處理操作示例

    這篇文章主要為大家詳細介紹了C#裁剪,縮放,清晰度,水印處理操作示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    吳 劍8332021-12-08
  • C#WPF 自定義雷達圖開發實例教程

    WPF 自定義雷達圖開發實例教程

    這篇文章主要介紹了WPF 自定義雷達圖開發實例教程,本文介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下...

    WinterFish13112021-12-06
  • C#Unity3D實現虛擬按鈕控制人物移動效果

    Unity3D實現虛擬按鈕控制人物移動效果

    這篇文章主要為大家詳細介紹了Unity3D實現虛擬按鈕控制人物移動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一...

    shenqingyu060520232410972022-03-11
  • C#深入解析C#中的交錯數組與隱式類型的數組

    深入解析C#中的交錯數組與隱式類型的數組

    這篇文章主要介紹了深入解析C#中的交錯數組與隱式類型的數組,隱式類型的數組通常與匿名類型以及對象初始值設定項和集合初始值設定項一起使用,需要的...

    C#教程網6172021-11-09
  • C#C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    這篇文章主要介紹了C# 實現對PPT文檔加密、解密及重置密碼的操作方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下...

    E-iceblue5012022-02-12
  • C#C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    這篇文章主要介紹了C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題,簡單描述了訪問者模式的定義并結合具體實例形式分析了C#使用訪問者模式解決長...

    GhostRider9502022-01-21
主站蜘蛛池模板: 亚洲一区二区在线播放 | 国产成人精品一区二区三区 | 亚洲国产精 | 久久亚洲国产 | 中文在线一区二区 | 午夜www| 小川阿佐美88av在线播放 | 国产一级在线 | 黄视频在线观看免费 | 91精品久久| 狠狠干最新网址 | 日韩精品中文字幕在线 | 日韩一二三区视频 | 天天夜夜操| 国产亚洲网站 | 欧美电影免费网站 | 欧美另类视频 | 久久久成人免费 | 日日日操 | av网站一区| 国产人妖一区二区 | 天天精品 | 青青草国产精品 | 999精品视频 | 在线免费视频一区二区 | 欧美视频免费看 | 黄色av影视| 欧美一区二区三区电影 | 欧美一级免费看 | 午夜精品美女久久久久av福利 | 噜噜噜视频在线观看 | 亚洲视频久久久 | 亚洲精品免费看 | 狠狠爱天天操 | 国产毛片毛片毛片 | 男女xx网站 | 日韩一区二区在线视频 | 人人澡人人射 | 龙珠z国语291集普通话 | 一级片黄 | 欧美午夜影院 |