本文重要纪录我在进修C#中foreach遍历道理的心得体会。
对鸠合中的要素举行遍历是一切编码中常常涉及到的操纵,因而大部分编程言语都把此历程写进了语法中,比方C#中的foreach。常常会看到下面的遍历代码:
var lstStr = new List<string> { "a", "b" }; foreach (var str in lstStr) { Console.WriteLine(str); }
实际此代码的实行历程:
var lstStr = new List<string> {"a", "b"}; IEnumerator<string> enumeratorLst = lstStr.GetEnumerator(); while (enumeratorLst.MoveNext()) { Console.WriteLine(enumeratorLst.Current); }
会发现有GetEnumerator()要领和IEnumerator<string>范例,这就涉及到可罗列范例和罗列器的观点。
为了轻易明白,以下为非泛型示例:
// 择要: // 公然罗列器,该罗列器支撑在非泛型鸠合上举行简朴迭代。 public interface IEnumerable { // 择要: // 返回一个轮回接见鸠合的罗列器。 // // 返回效果: // 可用于轮回接见鸠合的 System.Collections.IEnumerator 对象。 IEnumerator GetEnumerator(); }
完成了此接口的类称为可罗列范例,是能够用foreach举行遍历的标志。
要领GetEnumerator()的返回值是罗列器,能够明白为游标。
// 择要: // 支撑对非泛型鸠合的简朴迭代。 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):
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这个关键字今后,我们能够经由过程如许的体式格局来建立罗列器:
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); } }
以上就是C#中关于foreach完成的道理详解的细致内容,更多请关注ki4网别的相干文章!