一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

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

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

服務器之家 - 編程語言 - C# - C#中foreach實現原理詳解

C#中foreach實現原理詳解

2022-01-22 21:07阿瓏 C#

這篇文章主要為大家詳細介紹了C#中foreach實現原理,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文主要記錄我在學習C#中foreach遍歷原理的心得體會。

對集合中的要素進行遍歷是所有編碼中經常涉及到的操作,因此大部分編程語言都把此過程寫進了語法中,比如C#中的foreach。經常會看到下面的遍歷代碼:

?
1
2
3
4
5
var lstStr = new List<string> { "a", "b" };
   foreach (var str in lstStr)
      {
        Console.WriteLine(str);
      }

實際此代碼的執行過程:

?
1
2
3
4
5
6
var lstStr = new List<string> {"a", "b"};
   IEnumerator<string> enumeratorLst = lstStr.GetEnumerator();
   while (enumeratorLst.MoveNext())
      {
        Console.WriteLine(enumeratorLst.Current);
      }

會發現有GetEnumerator()方法和IEnumerator<string>類型,這就涉及到可枚舉類型和枚舉器的概念。

為了方便理解,以下為非泛型示例:

?
1
2
3
4
5
6
7
8
9
10
11
// 摘要:
//   公開枚舉器,該枚舉器支持在非泛型集合上進行簡單迭代。
  public interface IEnumerable
  {
    // 摘要:
    //   返回一個循環訪問集合的枚舉器。
    //
    // 返回結果:
    //   可用于循環訪問集合的 System.Collections.IEnumerator 對象。
    IEnumerator GetEnumerator();
  }

實現了此接口的類稱為可枚舉類型,是可以用foreach進行遍歷的標志。

方法GetEnumerator()的返回值是枚舉器,可以理解為游標。

?
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
// 摘要:
//   支持對非泛型集合的簡單迭代。
  public interface IEnumerator
  {
    // 摘要:
    //   獲取集合中的當前元素。
    //
    // 返回結果:
    //   集合中的當前元素。
    //
    // 異常:
    //  System.InvalidOperationException:
    //   枚舉數定位在該集合的第一個元素之前或最后一個元素之后。
    object Current { get; }
 
    // 摘要:
    //   將枚舉數推進到集合的下一個元素。
    //
    // 返回結果:
    //   如果枚舉數成功地推進到下一個元素,則為 true;如果枚舉數越過集合的結尾,則為 false。
    //
    // 異常:
    //  System.InvalidOperationException:
    //   在創建了枚舉數后集合被修改了。
    bool MoveNext();
    //
    // 摘要:
    //   將枚舉數設置為其初始位置,該位置位于集合中第一個元素之前。
    //
    // 異常:
    //  System.InvalidOperationException:
    //   在創建了枚舉數后集合被修改了。
    void Reset();
  }

以下是自定義一個迭代器的示例(https://msdn.microsoft.com/en-us/library/system.collections.ienumerator.aspx):

 

?
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
using System;
using System.Collections;
 
// Simple business object.
public class Person
{
  public Person(string fName, string lName)
  {
    this.firstName = fName;
    this.lastName = lName;
  }
 
  public string firstName;
  public string lastName;
}
 
// Collection of Person objects. This class
// implements IEnumerable so that it can be used
// with ForEach syntax.
public class People : IEnumerable
{
  private Person[] _people;
  public People(Person[] pArray)
  {
    _people = new Person[pArray.Length];
 
    for (int i = 0; i < pArray.Length; i++)
    {
      _people[i] = pArray[i];
    }
  }
 
// Implementation for the GetEnumerator method.
  IEnumerator IEnumerable.GetEnumerator()
  {
    return (IEnumerator) GetEnumerator();
  }
 
  public PeopleEnum GetEnumerator()
  {
    return new PeopleEnum(_people);
  }
}
 
// When you implement IEnumerable, you must also implement IEnumerator.
public class PeopleEnum : IEnumerator
{
  public Person[] _people;
 
  // Enumerators are positioned before the first element
  // until the first MoveNext() call.
  int position = -1;
 
  public PeopleEnum(Person[] list)
  {
    _people = list;
  }
 
  public bool MoveNext()
  {
    position++;
    return (position < _people.Length);
  }
 
  public void Reset()
  {
    position = -1;
  }
 
  object IEnumerator.Current
  {
    get
    {
      return Current;
    }
  }
 
  public Person Current
  {
    get
    {
      try
      {
        return _people[position];
      }
      catch (IndexOutOfRangeException)
      {
        throw new InvalidOperationException();
      }
    }
  }
}
 
class App
{
  static void Main()
  {
    Person[] peopleArray = new Person[3]
    {
      new Person("John", "Smith"),
      new Person("Jim", "Johnson"),
      new Person("Sue", "Rabon"),
    };
 
    People peopleList = new People(peopleArray);
    foreach (Person p in peopleList)
      Console.WriteLine(p.firstName + " " + p.lastName);
 
  }
}
 
/* This code produces output similar to the following:
 *
 * John Smith
 * Jim Johnson
 * Sue Rabon
 *
 */

在有了yield這個關鍵字以后,我們可以通過這樣的方式來創建枚舉器:

?
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
using System;
using System.Collections;
 
// Simple business object.
public class Person
{
  public Person(string fName, string lName)
  {
    this.firstName = fName;
    this.lastName = lName;
  }
 
  public string firstName;
  public string lastName;
}
 
// Collection of Person objects. This class
// implements IEnumerable so that it can be used
// with ForEach syntax.
public class People : IEnumerable
{
  private Person[] _people;
 
  public People(Person[] pArray)
  {
    _people = new Person[pArray.Length];
 
    for (int i = 0; i < pArray.Length; i++)
    {
      _people[i] = pArray[i];
    }
  }
 
  // Implementation for the GetEnumerator method.
  IEnumerator IEnumerable.GetEnumerator()
  {
    for (int i = 0; i < _people.Length; i++)
    {
      yield return _people[i];
    }
  }
 
}
 
 
class App
{
  static void Main()
  {
    Person[] peopleArray = new Person[3]
    {
      new Person("John", "Smith"),
      new Person("Jim", "Johnson"),
      new Person("Sue", "Rabon"),
    };
 
    People peopleList = new People(peopleArray);
    foreach (Person p in peopleList)
      Console.WriteLine(p.firstName + " " + p.lastName);
  }
}

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

原文鏈接:http://www.cnblogs.com/alongdada/archive/2017/09/26/7598119.html

延伸 · 閱讀

精彩推薦
  • C#WPF 自定義雷達圖開發實例教程

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

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

    WinterFish13112021-12-06
  • C#C#實現XML文件讀取

    C#實現XML文件讀取

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

    Just_for_Myself6702022-02-22
  • C#Unity3D實現虛擬按鈕控制人物移動效果

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

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

    shenqingyu060520232410972022-03-11
  • C#C#通過KD樹進行距離最近點的查找

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

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

    帆帆帆6112022-01-22
  • C#C# 實現對PPT文檔加密、解密及重置密碼的操作方法

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

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

    E-iceblue5012022-02-12
  • C#深入解析C#中的交錯數組與隱式類型的數組

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

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

    C#教程網6172021-11-09
  • C#C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

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

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

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

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

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

    吳 劍8332021-12-08
主站蜘蛛池模板: 免费免费啪视频在线观播放 | 天天干天天色综合网 | 成人免费在线视频网 | 朝鲜女人性猛交 | 欧美亚洲国产精品久久第一页 | 欧美在线播放一区二区 | 校草让我脱了内裤给全班看 | 福利社在线免费观看 | 日韩天堂网 | www视频在线免费观看 | 午夜精品久久久久久久99蜜桃 | 1769亚洲欧美资源站 | 色啪啪888.com| 成人影院vs一区二区 | 王的视频视ivk | 91精品大神国产在线播放 | 青青草亚洲| 日日操免费视频 | 人妖三级| 娇妻被老外疯狂调教 | 青草国产福利视频免费观看 | 日产乱码卡1卡2卡三卡四在线 | 国产精品www夜色影视 | 99re这里只有精品视频 | 日本 在线播放 | 校花小雪灌满了男人们的浓浆 | 国产精品嫩草影院在线 | 色淫阁小说 | 国产一区二区三区高清视频 | 国产第一页无线好源 | 波多野结衣久久国产精品 | 亚洲乱人伦在线 | 美女啪啪国产 | 色中色导航 | 亚洲天堂男人网 | 亚洲AV无码专区国产精品麻豆 | 精品视频中文字幕 | 四虎论坛 | 日韩操片| 久久久大香菇 | 亚洲精品综合一二三区在线 |