C#从foreach语句中枚举元素看数组详解
2017-05-11 09:51
701 查看
前言
在foreach语句中使用枚举,可以迭代数组或集合中的元素,且无须知道集合中的元素的个数。如图显示了调用foreach方法的客户端和集合之间的关系。数组或集合实现带
GetEnumerator()方法的IEnumerable接口。
GetEnumerator()方法返回一个实现lEnumerable接口的枚举,接着foreach语句就可以使用IEnumerable接口迭代集合了。
GetEnumerator()方法用IEnumerable接口定义,foreach语句并不真的需要在集合类中实现这个接口。有一个名为
GetEnumerator()的方法它返回实现了IEnumerator接口的对象就足够了。
先定义一个Person类,这个类有自动实现的属性Firstname和Lastname,以及从Object类重写ToString方法和继承泛型接口IEquatable以比较两个对象是否相等,实现泛型接口IComparer以比较两个对象用来排序。
public class Person : IEquatable<Person>,IComparable<Person> { public int Id { get; private set; } public string FirstName { get; set; } public string LastName { get; set; } public override string ToString() { return String.Format("{0}, {1} {2}", Id, FirstName, LastName); } public bool Equals(Person other) { if (other == null) return base.Equals(other); return this.FirstName == other.FirstName && this.LastName == other.LastName; } public int CompareTo(Person other) { if (other == null) throw new ArgumentNullException("other"); int result = this.LastName.CompareTo(other.LastName); if (result == 0) { result = this.FirstName.CompareTo(other.FirstName); } return result; } }
创建一个三个元素的person数组,现对数组进行排序在用foreach循环访问数组中的元素并输出
Person[] persons = { new Person { FirstName = "Simen03", LastName = "Go" }, new Person { FirstName = "Simen02", LastName = "Go" }, new Person { FirstName = "Simen01", LastName = "Go" } }; Array.Sort(persons); foreach (var person in persons) Console.WriteLine(person);
分析
foreach (var person in persons)Console.WriteLine(person);这段代码IL代码
// loop start (head: IL_009b) IL_008a: ldloc.2 IL_008b: ldloc.3 IL_008c: ldelem.ref IL_008d: stloc.s person IL_008f: ldloc.s person IL_0091: call void [mscorlib]System.Console::WriteLine(object) IL_0096: nop IL_0097: ldloc.3 IL_0098: ldc.i4.1 IL_0099: add IL_009a: stloc.3 IL_009b: ldloc.3 IL_009c: ldloc.2 IL_009d: ldlen IL_009e: conv.i4 IL_009f: blt.s IL_008a // end loop
C#的foreach语句不会解析为IL代码中的foreach语句,C#编译器会把foreach语句转换为IEnumerable接口的方法和属性,foreach语句使用IEnumerator接口的方法和属性,迭代数组中的所有元素,为此,IEnumerator定义了Current属性,来返回光标所在的元素,该接口的
MoveNext()方法移动到数组的下一个元素上,如果有这个元素该方法就返回true否则返回false,这个接口的泛型版本IEnumerator派生自接口IDisposable,因此定义了
Dispose()方法来清理枚举器占用的资源,使用foreach语句会解析为下面的代码段
IEnumerator enumerator = persons.GetEnumerator(); while (enumerator.MoveNext()) { var person = enumerator.Current; Console.WriteLine(person); }
为了方便的创建枚举器,C#添加了yield语句,yield return 语句返回集合的一个元素,并移动到下一个元素,yield break 可停止迭代。使用迭代块,编译器会生成一个yield类型,其中包含一个状态机,如下代码段所示。yield 类型实现IEnumerator和IDisposable接口的属性和方法。在下面的例子中,可以把yield类型看作内部类Enumerator.外部类的
GetEnumerator()方法实例化并返回一个新的yield类型。在yield类型中,变量state定义了迭代的当前位置,每次调用
MoveNext()时,当前位置都会改变,
MoveNext()封装了迭代代码,并设置了current变量的值,从而使Current属性根据位置返回一个对象。
static void Main(string[] args) { var helloCollection = new HelloCollection(); foreach (string s in helloCollection) { Console.WriteLine(s); } } public class HelloCollection { public IEnumerator<string> GetEnumerator() { yield return "Hello"; yield return "World"; } } public class HelloCollectionOther { public IEnumerator GetEnumertor() { return new Enumerator(0); } public class Enumerator : IEnumerator<string>, IEnumerator, IDisposable { private int state; private string current; public Enumerator(int state) { this.state = state; } public string Current => throw new NotImplementedException(); object IEnumerator.Current { get { return current; } } public void Dispose() { throw new NotImplementedException(); } public bool MoveNext() { switch (state) { case 0:current = "hello"; state = 1; return true; case 1:current = "world"; state = 2; return true; case 2: break; } return false; } public void Reset() { throw new NotImplementedException(); } } }
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
您可能感兴趣的文章:
相关文章推荐
- 从foreach语句枚举元素看数组
- 从foreach语句枚举元素看数组
- C# 数组遍历 foreach 语句
- C#不允许在foreach循环中改变数组或集合中元素的值(注:成员的值不受影响)
- 对数组的每个元素仍是数组的遍历方法,c#,foreach,for
- 认真CS丨初始化数组元素、foreach语句
- C#使用linq语句查询数组中以特定字符开头元素的方法
- MyBatis的foreach语句详解,可解决界面传输的数组对象参数问题
- C#中用foreach语句遍历数组及将数组作为参数的用法
- C#使用foreach语句简单遍历数组的方法
- C#使用foreach语句访问数组
- [叩响C#之门]第5章 枚举、结构体和数组
- C#数组复制方法详解
- C# 取两个数组的相同元素
- 删除数组中重复的元素(C#实现)
- C# 定义多维数组,获取各维度的元素数
- [叩响C#之门]第5章 枚举、结构体和数组 5.2 结构体
- C#删除动态数组,按条件留下待选数组元素
- 用《叩响C#之门》复习C#基础知识 第五章 枚举、结构体和数组
- [C#]实现IEnumerable接口来使用foreach语句的一个实例