gpt4 book ai didi

C#中foreach实现原理详解

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 27 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章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#中foreach实现原理详解的文章就讲到这里了,如果你想了解更多关于C#中foreach实现原理详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com