Detailed C # iterators

 A, iterators (the Iterator) can get the current iteration element identification and the element to be next iteration by iteration holding state can be set to traverse each element without understanding the specific implementation set;

  Iterative methods implemented function is called iterator iterator method return type can be the following four types of interfaces in any one: of the namespace System.Collections IEnumerable, IEnumerator and the namespace System.Collections .Generic the IEnumerable <T>, IEnumerator <T>, and wherein the interface IEnumerable IEnumerator codes:

Copy the code
public interface IEnumerable
{
    IEnumerator GetEnumerator();
}
public interface IEnumerator
{
    object Current { get; }

    bool MoveNext();
    void Reset();
}
Copy the code

  ※ the corresponding generic interface IEnumerable <T> and IEnumerator <T> Code:

Copy the code
public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}
public interface IEnumerator<out T> : IDisposable, IEnumerator
{
    T Current { get; }
}
Copy the code

  ※ Interface IEnumerable declared in the acquired IEnumerator type of the object method of the GetEnumerator (), () implement the iterator function interface IEnumerator by property Current and methods of the MoveNext; custom type can IEnumerable have iterations function inherit an interface, and the interface IEnumerator iteration provide specific functions to achieve, both designed in line with the principle of single responsibility, and thus be on the same object at the same time a number of iterations;

  ※ get access can also be specified with a method iterator, but the events, constructors and destructors not declared iterator method; method of the iterator can not contain reference parameters;

  Second, the iterator method of internal state machine, but you can use the yield keyword to quickly implement the iterator method, using a yield return statement to add an element of iterations required, at the first iteration, would have been the first to perform a yield return statement and save the current iteration state, will continue in the next iteration from each pause position to the next iteration yield return statement and save the state (MoveNext () method returns true and the value of the current iteration is assigned to current), until iterator reaches the end (the MoveNext () method returns false) to complete the current iteration; yield break statement may also be used in an iterative process immediately ends the present iteration:

IEnumerable<int> MyIterator()
{
    yield return 10;
    yield return 20;
}

  Wherein ※ yield return statement return value needs to be converted to the implicit method return type iterator IEnumerable <T> type parameter value;

  ※ This is a syntactic sugar compiler prepared for us, the compiler will convert it to use a state machine implemented implements the interface IEnumerable <T> nested class, see the IL code in the iterator method, you can see the compiler the state machine generates a nested class:

  Third, for the realization of an interface IEnumerable or IEnumerable <T> object type, can be traversed using foreach:

the foreach (int item in MyIterator ()) 
{ 
    // do ... Where item type int, a value of 10 and 20, respectively 
}

  ※ wherein the item type is in fact the GetEnumerator () method returns the value of the Current property types, i.e., so the type of the attribute type generally used var said inferred by the compiler, for example, when traversing a hash table:

the foreach (var item in myHashTable) 
{ 
    // ... do DictionaryEntry item is a type wherein, item.Key and item.Value 
}

  Current ※ Since only a get property accessors, and therefore can not carry out the assignment item (= operator operation) in a foreach loop, but may be modified and calls its detailed object member;

  ※ when traversing a collection of objects built in, if the set length is changed, the disorder is likely iterative process, and therefore can not carry out any operation to modify the length of the set when the set of objects iteration, otherwise an exception is thrown an InvalidOperationException;

  Fourth, in addition to using the foreach, but also manually iterated to achieve the object type for generic interface requires manual iterations using statement to call Dispose Shihai iteration is completed after it () Method:

using (IEnumerator<int> enumerator = MyIterator().GetEnumerator())

Copy the code
{ 
    // At this myEnmerator.Current default value for the type of 
    the while (enumerator.MoveNext ()) 
    { 
        // do ... which can be accessed via the iterator value enumerator.Current 
    } 
}    
Copy the code

  1. For only implements the interface IEnumerator or IEnumerator <T> object type, only manually iterative:

Copy the code
IEnumerator<int> MyIterator()
{
    yield return 1;
    yield return 2;
}
using (IEnumerator<int> enumerator = MyIterator())
{
    while (enumerator.MoveNext())
    {
        //do…
    }
}
Copy the code

  2. Can <T> interfaces, the compiler will automatically Current properties of the interface, or by implementing an interface IEnumerable IEnumerable <T> is defined from the iterator type, this time without having to manually implement IEnumerator or IEnumerator, MoveNext (), Reset () and Dispose () method:

Copy the code
public class MyIterator : IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        yield return 10;
        yield return 20;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        Console.WriteLine("Non-Generic GetEnumerator");
        return GetEnumerator(); //注意这里不是yield return
        //或者手动进行迭代:
        //using (IEnumerator<int> iterator = this.GetEnumerator())
        //{
        //while (iterator.MoveNext())
        //{
        //yield return iterator.Current;
        //}
        //}
    }
}    
Copy the code

  ※ In this case, when using foreach to traverse, if you use var, automatically inferred by the compiler item type int, and calls the generic interface to achieve, if the item type is specified as object type, the call will still be generic interface implementation, but it will produce packing operation:

foreach (var item in new MyIterator ( )) // or explicitly specified as int: int Item 
{ 
    Console.WriteLine (Item); 20 is // 10 
}

  ※ At this time, when using foreach traversal, if it is converted to an object of type IEnumerable achieve non-generic interface is invoked, the compiler will automatically infer item type object, and generates a packing operation:

foreach (var item in (IEnumerable) new MyIterator ()) // or explicitly specified as Object: Object Item 
{ 
    Console.WriteLine (Item); // Non-20 is the Generic the GetEnumerator 10 
}

  3. Direct call the Reset method or the iterator iterator type auto-generated () method throws an exception when NotSupportedException, to start again from scratch iteration, you must obtain a new iterator, or manually achieve Reset the iterator type ( )method;

 


If you feel that you have read this article to help, please click the "recommend" button, your recognition is the greatest power of my writing!

Author: Minotauros
Source: https://www.cnblogs.com/minotauros/

This article belongs to the author and blog Park total, welcome to reprint, but without the author's consent declared by this section must be retained, and given the original connection in the apparent position of the article page, otherwise the right to pursue legal responsibilities.

Guess you like

Origin www.cnblogs.com/gaoxianzhi/p/11946764.html