Introduction
IEnumerable is the base interface of all non generic collections that can be enumerated. IEnumerable contains a method GetEnumerator(), which returns an IEnumerator. IEnumerator provides the function of circular access to the collection through the Current property and MoveNext() and Reset() methods.
IEnumerable interface
Exposes enumerators that support simple iterations over non generic collections. The interface source code is as follows:
public interface IEnumerable { [DispId(-4), __DynamicallyInvokable] IEnumerator GetEnumerator(); }
IEnumerator interface
Supports simple iterations of non generic collections. The interface source code is as follows:
public interface IEnumerator { [__DynamicallyInvokable] bool MoveNext(); [__DynamicallyInvokable] object Current { [__DynamicallyInvokable] get; } [__DynamicallyInvokable] void Reset(); }
Illustrate with examples
The example demonstrates the best practice of implementing the IEnumerable and IEnumerator interfaces to iterate through custom collections.
Define a simple entity class:
public class Person { public Person(string name, int age) { this.Name = name; this.Age = age; } public string Name; public int Age; }
Define a collection of entity classes, inherit IEnumerate:
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]; } } /// <summary> /// GetEnumerator Method implementation /// </summary> /// <returns></returns> IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public PeopleEnum GetEnumerator() { return new PeopleEnum(_people); } }
Define an enumerator that inherits IEnumerator:
public class PeopleEnum : IEnumerator { public Person[] _people; /// <summary> /// Enumerator before first element until first MoveNext()Call. /// </summary> private 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 => Current; public Person Current { get { try { return _people[position]; } catch (IndexOutOfRangeException) { throw new InvalidOperationException(); } } } }
Specific call:
Person[] peopleArray = new Person[3] { new Person("Zhang San", 15), new Person("Li Si", 18), new Person("Wang Wu", 21), }; People peopleList = new People(peopleArray); foreach (Person p in peopleList) Console.WriteLine(p.Name + "\t" + p.Age);
Output:
Where foreach is equivalent to
IEnumerator enumeratorSimple = peopleList.GetEnumerator(); while (enumeratorSimple.MoveNext()) { Person p = enumeratorSimple.Current as Person; Console.WriteLine(p?.Name + "\t" + p?.Age); }
Through examples, we can get:
- Implement a custom set, inherit from IEnumerate, must implement an enumerator;
- The foreach statement of C ා language hides the complexity of enumerators. Therefore, foreach is recommended to use instead of directly operating enumerators;
- Enumerators can be used to read data from a collection, but not to modify the underlying collection.
summary
IEnumerable represents the class that inherits this interface (such as ArrayList, IList, list < T >), which can obtain an IEnumerator to enumerate the elements in the collection contained in this class. It is the most basic collection accessor in the. NET Framework. In programming, the variable returned by Lambda expression through Select() or Where() is ienumerate < T >. At this time, we can traverse through foreach. I hope this article can help you. The next one introduces Select and Where in Lambda. Interested friends can pay more attention. Welcome to leave a message!