C # Basic Knowledge series 9 (confused about IEnumerable and IEnumerator interfaces)

Source: Internet
Author: User

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.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.