IEnumerable and IEnumerator do not understand these two interfaces until now. They do not understand them, but they always want to try to understand them. After all, they use less, so record them here. In the future, I hope that the big cows in the garden will help me to see what I understand.
Next, let's take a look at the definitions of the two interfaces.
Let's take a look at the IEnumerable interface. After reading this interface, we find that it is actually very simple. It only contains one method, GetEnumerator (), and it returns an IEnumerator object that can be used to access the set cyclically, as shown below:
Here, the IEnumerator object is actually another interface. What is this interface object? It is a real set accesser. Without it, you cannot use the foreach statement to traverse the set or array, because only the IEnumerator object can access items in the set, if the items in the set cannot be accessed, it is impossible to traverse the set cyclically. Let's see what the IEnumerator interface defines.
From the above we know that the IEnumerator interface defines a Current attribute, MoveNext and Reset methods. how simple this is. Since the IEnumerator object is an accessors. There should be at least one Current attribute to get the items in the Current set. The MoveNext method only moves the internal position of the cursor forward (that is, moving to an element). How can we avoid moving forward for loop traversal?
They can also be clearly identified through annotations.
Here is a simple example:
static void Main(string[] args) { int[] iArr = { 1, 3, 4, 6, 7, 9 }; foreach (int i in iArr) { Console.WriteLine(i.ToString()); } Console.ReadLine(); }
F5 to run the code
The result indicates that a simple array supports the foreach loop.
Let's take a small example here to define the object class first.
/// <Summary> /// individual object class /// </summary> public class Person {public string Name {get; set;} public int Age {get; set ;}//< summary> // entity class of a group of People /// </summary> public class People {Person [] personList = new Person [4]; public People () {personList [0] = new Person () {Name = "aehyok", Age = 25}; personList [1] = new Person () {Name = "Kris", Age = 22}; personList [2] = new Person () {Name = "Leo", Age = 21 }; personList [3] = new Person () {Name = "Niki", Age = 23 };}}
As shown in the code above, a Person class is a personal entity class, and then the People class is an entity class of a group of People. Following the format similar to the preceding array, we will call
Static void Main (string [] args ){
/// Perform foreach People people = new People (); foreach (Person p in people) {Console. writeLine ("Name: {0} \ tAge {1}", p. name, p. age);} Console. readLine ();}
Before compilation, the error will come.
So let's implement the IEnumerable interface of the People class according to the above explanation. Modify the People object class first.
/// <Summary> /// individual object class /// </summary> public class Person {public string Name {get; set;} public int Age {get; set ;}//< summary> // entity class of a group of People /// </summary> public class People: IEnumerable {Person [] personList = new Person [4]; public People () {personList [0] = new Person () {Name = "aehyok", Age = 25 }; personList [1] = new Person () {Name = "Kris", Age = 22}; personList [2] = new Person () {Name = "Leo ", age = 21}; personList [3] = new Person () {Name = "Niki", Age = 23};} public IEnumerator GetEnumerator () {return this. personList. getEnumerator ();}}
Inherit the implementation interface. After completing this method, you can use foreach during the call.
Note: you do not need to inherit this interface here. Implement the GetEnumerator () method directly, and then return IEnumerator.
In this way, another call method can be provided.
Static void Main (string [] args) {People people = new People (); foreach (Person p in people) {Console. writeLine ("Name: {0} \ tAge {1}", p. name, p. age);} Console. writeLine (""); // get the iterator IEnumerator I = people. getEnumerator (); while (I. moveNext () {Person person Person = (Person) I. current; Console. writeLine ("Name: {0} \ tAge {1}", person. name, person. age);} Console. readLine ();}
Call result
In the above example, we inherited the interfaces in the Microsoft class library to implement the foreach traversal of object sets. Next, we will demonstrate how to use the self-created interface to implement the foreach traversal of the Instance set defined by myself. First, we will implement a simple iterator.
Step 1: Define an interface IMyEnumerator, which will be implemented by all later iterators
/// <Summary> /// all iterators must implement this interface. /// </summary> interface IMyEnumerator {bool MoveNext (); object Current {get ;};}
Step 2: Define another interface IMyEnumerable. All sets must implement this interface.
/// <Summary> /// all sets must implement this interface. // in this way, the client can encode the interface // without paying attention to the specific implementation // </summary> interface IMyEnumerable {IMyEnumerator GetEnumerator (); int Count {get ;};}
Step 3: A simple collection class MyList to implement IMyEnumerable.
class MyList:IMyEnumerable { int[] items = {0,1,2,3,4,5,6,7,8,9}; IMyEnumerator myEnumerator; public int this[int i] { get { return items[i]; } set { this.items[i] = value; } } public int Count { get { return items.Length; } } public IMyEnumerator GetEnumerator() { if (myEnumerator == null) { myEnumerator = new MyEnumerator(this); } return myEnumerator; } }
Step 4: In fact, we also need to use the iterator that implements the first step in the set, so we need to implement this iterator here.
public class MyEnumerator:IMyEnumerator { int index = 0; MyList myList; public MyEnumerator(MyList myList) { this.myList = myList; } public bool MoveNext() { if (index + 1 > =myList.Count) { index = 1; return false; } else { index++; return true; } } public object Current { get { return myList[index]; } } }
Step 5: simple call for debugging
Static void Main (string [] args) {// use the interface IMyEnumerable to replace MyList IMyEnumerable list = new MyList (); // get the iterator, encode the iterator in the loop, instead of the Set MyList IMyEnumerator enumerator = list. getEnumerator (); for (int I = 0; I <list. count; I ++) {object current = enumerator. current; Console. writeLine (current. toString (); enumerator. moveNext ();} Console. writeLine (""); // recreate a new object IMyEnumerable list1 = new MyList (); IMyEnumerator enumerator1 = list1.GetEnumerator (); while (enumerator1.MoveNext ()) // because one digit is removed, {object current = enumerator1.Current; Console starts from 1. writeLine (current. toString ();} Console. readLine ();}
Call result
In fact, the two interfaces I have defined use IMyEnumerable and IMyEnumerator. Here you can directly remove My, which is the interface in the Microsoft class library. Here I just want to customize it, then I define the method attributes of the interface, which is not strictly defined according to Microsoft's interface. However, it is almost the same. I only need to make a simple correction to call the interface. Here is a version.
View Code
In fact, we can use foreach to call the call in the above example. Now let's use foreach to call it.
static void Main(string[] args) { MyList list=new MyList(); foreach (object obj in list) { Console.WriteLine(obj.ToString()); } Console.ReadLine(); }
The following simple examples show that a type that supports foreach traversal can be:
1. The first solution is: this class implements the IEnumerable interface.
2. The second solution is: this class has a public GetEnumerator instance method (without inheriting the IEnumerable implementation Interface), and the return type contains public bool MoveNext () the Current instance attribute of the instance method and public.
A set of IEnmerable <T> interfaces is strongly typed. It provides a safer type for the iteration of sub-objects.
I realized it myself, and I still understood it. Although I haven't fully understood it yet, at least I know what's going on. If you have time, let's take a look at the usage of the yield keyword.