C# Study Notes--Understand IEnumerable and IEnumerator from shallow to deep

foreword

In the last article, I implemented a container C# study notes by myself – implementing a container that can repeat weights and can be automatically sorted – MultiplySortedSet

After writing, I suddenly thought of a question, how does the container traverse?
The for loop can use subscripts to traverse the array, but how does the for loop traverse the unordered collection? Then you have to use foreach .
But how does foreach traverse the collection? Since it is unordered, how do you find the next element?
With these questions, I have studied IEnumerable and IEnumerator .

IEnumerable 和 IEnumerator

What is IEnumerable?

Let's take a look at the definition of C#

namespace System.Collections
{
    
    
    public interface IEnumerable
    {
    
    
        IEnumerator GetEnumerator();
    }
}

Simply put, the IEnumerable interface defines a GetEnumerator method that returns an object that implements the IEnumerator interface.

I definitely can't understand it at the first time, but we can try to translate

  • IEnumerable: iterable
  • Enumerator: iterator

Let's look at List and Dictionary again

public class List<T> : ICollection<T>, IEnumerable<T>, IEnumerable, IList<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection, IList
public class Dictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IReadOnlyDictionary<TKey, TValue>, ICollection, IDictionary, IDeserializationCallback, ISerializable

List and Dictionary can be traversed by foreach loop because they implement IEnumerable < T > and IEnumerable interfaces.

Having said that, I didn't say how to traverse it?
Don't worry, let's take a look at IEnumerator again

What is IEnumerator?

As usual, first look at the C# definition

namespace System.Collections
{
    
    
    public interface IEnumerator
    {
    
    
        object Current {
    
     get; }

        bool MoveNext();
        void Reset();
    }
}

let's look at two things

  • object Current { get; }
  • bool MoveNext();

MoveNext , the translation is to move to the next one.
And Current is actually the current value.

It's useless to say more, just write a program to see

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour
{
    
    
    private void Awake()
    {
    
    
        int[] array = new int[3] {
    
     1, 2, 3 };
        var it = array.GetEnumerator();//获取对象的迭代器

        while (it.MoveNext())
        {
    
    
            print(it.Current);
        }
    }
}

insert image description here
The internal principle is actually like this, below is the pseudo code

private int index = -1;
private int[] array;

public int Current
{
    
    
    get
    {
    
    
    	if(index == -1) return null;
        return array[index];
    }
}

public bool MoveNext()
{
    
    
	if(index < array.Length)
	{
    
    
		index++;
		return true;
	}
	else
	{
    
    
		return false;
	}
}

There is a pointer inside the iterator (of course, this pointer is not necessarily a pointer in C++, it is just a way of expression, of course, this pointer can also be the subscript of the array: index )

In our last example, the pointer initially pointed to NULL. That is, the index points to -1, and the Current is null
insert image description here
when we call MoveNext . That is, the index points to 0, at this time the Current is 1
insert image description here
and then MoveNext is called all the time ...

When index = 2 , that is, pointing to element 3
insert image description here

We call MoveNext again and find that there is no next element. At this time, MoveNext returns false
and the while loop is terminated.

Summarize

  • The IEnumerable interface defines a GetEnumerator method that returns an object that implements the IEnumerator interface.
  • Whereas the IEnumerator interface defines methods for traversing a sequence, such as MoveNext and Current .

ending trailer

In the next article, let's study how the foreach loop traverses the container

Guess you like

Origin blog.csdn.net/qq_52855744/article/details/130601250