C # iterator,

Source: Internet
Author: User
Tags finally block

C # iterator,
1. Overview

The iterator is used to traverse a set. Iterators can be defined as methods or get accessors. You cannot use an iterator in event, instance constructor, static constructor, or static destructor.

The yield keyword is specially designed for the iterator. You can use yield to define the iterator. When implementing the IEnumerable and IEnumerator interfaces to customize the set, no other explicit classes are required (saving the enumeration status ).

The yield statement has two forms:

yield return <expression>;yield break;

The yield return Statement returns an element at a time: each iteration of the foreach statement or LINQ query calls the corresponding iteration method. When the iteration method runs to the yield return statement, an expression is returned, and keep the current running position. The next time you call the iterator function, it starts directly from this position.

The yield break statement is used to terminate an iteration.

Iterator method and get accessors

The iterator declaration must meet the following conditions:

  • The return type must be IEnumerable, IEnumerable <T>, or IEnumerator <T>.
  • The Declaration cannot contain the ref or out parameter.

Return the iterator of IEnumerable or IEnumerator. Its yield type is object. If the type returned by the iterator is IEnumerable <T> or IEnumerator <T>Yield returnThe expression type of the statement is implicitly converted to the type of the generic type parameter.

Methods With the following features cannot includeYield returnOrYield breakStatement:

  • Anonymous method.
  • Contains unsafe blocks.
Exception Handling

You cannot setYield returnThe statement is placed in the try-catch Block, but can be placed in the try block of the try-finally statement.

Yield breakStatements can be placed in try or catch blocks, but not in finally blocks.

If a foreach Statement (outside the iterator) encounters an exception, the finally block of the iterator is executed.

Implementation

Although we define the iterator as a method, the compiler will convert it into a nested class. This class records the iterator position.

When creating an iterator for a class, you do not need to fully implement the IEnumerator interface. When the compiler detects the iterator, it automatically generates the Current, MoveNext, and Dispose methods for the IEnumerator or IEnumerator <T> interfaces.

The iterator does not support the IEnumerator. Reset method. to traverse the iterator again, you must obtain a new iterator.

The following code first returns IEnumerable <string> from an iterator and then traverses its elements:

IEnumerable<string> elements = MyIteratorMethod();foreach (string element in elements){   …}

When calling MyIteratorMethodForeachDuring the loop, the MoveNext method is called for elements to actually execute the traversal operation until the next yield return statement.

In each subsequent iteration of the foreach loop, the execution of the iterator body continues from its paused position until it reaches the yield return statement. When the iterator method ends or the yield break statement is reached, the foreach loop is completed.

2. Example
public class PowersOf2{    static void Main()    {        // Display powers of 2 up to the exponent of 8:        foreach (int i in Power(2, 8))        {            Console.Write("{0} ", i);        }    }    public static System.Collections.IEnumerable<int> Power(int number, int exponent)    {        int result = 1;        for (int i = 0; i < exponent; i++)        {            result = result * number;            yield return result;        }    }    // Output: 2 4 8 16 32 64 128 256}

In the preceding example, The for loop contains a yield return statement. The foreach loop in Main calls the Power iterator function each iteration. Each call to the iterator function starts from the last point.

public static class GalaxyClass{    public static void ShowGalaxies()    {        var theGalaxies = new Galaxies();        foreach (Galaxy theGalaxy in theGalaxies.NextGalaxy)        {            Debug.WriteLine(theGalaxy.Name + " " + theGalaxy.MegaLightYears.ToString());        }    }    public class Galaxies    {        public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy        {            get            {                yield return new Galaxy { Name = "Tadpole", MegaLightYears = 400 };                yield return new Galaxy { Name = "Pinwheel", MegaLightYears = 25 };                yield return new Galaxy { Name = "Milky Way", MegaLightYears = 0 };                yield return new Galaxy { Name = "Andromeda", MegaLightYears = 3 };            }        }    }    public class Galaxy    {        public String Name { get; set; }        public int MegaLightYears { get; set; }    }}
In the previous example, an iterator in the form of get accessors is demonstrated. In this example, each yield return Statement returns an instance of a user-defined class. 2. Create a collection class

In this example, the DaysOfTheWeek class implements the IEnumerable interface, that is, the GetEnumerator method is provided. When the DaysOfTheWeek collection class is iterated, the compiler implicitly calls the GetEnumerator method to obtain IEnumerator. The GetEnumerator method returns a string each time using the yield return statement.

static void Main(){    DaysOfTheWeek days = new DaysOfTheWeek();    foreach (string day in days)    {        Console.Write(day + " ");    }    // Output: Sun Mon Tue Wed Thu Fri Sat    Console.ReadKey();}public class DaysOfTheWeek : IEnumerable{    private string[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };    public IEnumerator GetEnumerator()    {        for (int index = 0; index < days.Length; index++)        {            // Yield each day of the week.            yield return days[index];        }    }}
3. Generic iterator
static void Main(){    Stack<int> theStack = new Stack<int>();    //  Add items to the stack.    for (int number = 0; number <= 9; number++)    {        theStack.Push(number);    }    // Retrieve items from the stack.    // foreach is allowed because theStack implements    // IEnumerable<int>.    foreach (int number in theStack)    {        Console.Write("{0} ", number);    }    Console.WriteLine();    // Output: 9 8 7 6 5 4 3 2 1 0    // foreach is allowed, because theStack.TopToBottom    // returns IEnumerable(Of Integer).    foreach (int number in theStack.TopToBottom)    {        Console.Write("{0} ", number);    }    Console.WriteLine();    // Output: 9 8 7 6 5 4 3 2 1 0    foreach (int number in theStack.BottomToTop)    {        Console.Write("{0} ", number);    }    Console.WriteLine();    // Output: 0 1 2 3 4 5 6 7 8 9    foreach (int number in theStack.TopN(7))    {        Console.Write("{0} ", number);    }    Console.WriteLine();    // Output: 9 8 7 6 5 4 3    Console.ReadKey();}public class Stack<T> : IEnumerable<T>{    private T[] values = new T[100];    private int top = 0;    public void Push(T t)    {        values[top] = t;        top++;    }    public T Pop()    {        top--;        return values[top];    }    // This method implements the GetEnumerator method. It allows    // an instance of the class to be used in a foreach statement.    public IEnumerator<T> GetEnumerator()    {        for (int index = top - 1; index >= 0; index--)        {            yield return values[index];        }    }    IEnumerator IEnumerable.GetEnumerator()    {        return GetEnumerator();    }    public IEnumerable<T> TopToBottom    {        get { return this; }    }    public IEnumerable<T> BottomToTop    {        get        {            for (int index = 0; index <= top - 1; index++)            {                yield return values[index];            }        }    }    public IEnumerable<T> TopN(int itemsFromTop)    {        // Return less than itemsFromTop if necessary.        int startIndex = itemsFromTop >= top ? 0 : top - itemsFromTop;        for (int index = top - 1; index >= startIndex; index--)        {            yield return values[index];        }    }}

In the preceding example, the Stack <T> generic class implements the IEnumerable <T> generic interface. The Push method adds the T type value to the array. The GetEnumerator method uses the yield return statement to include the array value.

In addition to the generic GetEnumerator method, you must also implement the non-generic GetEnumerator method. Because IEnumerable <T> is inherited from IEnumerable. Non-generics are directly implemented through generics.

This example uses the named iterator to support multiple Iteration Methods for the same set. The name iterator includes the TopToBottom, BottomToTop, and TopN methods.

The BottomToTop attribute uses the iterator in the get accessors.

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.