C# Tips

Today's C# Tip

foreach creates new iterator for IEnumerable

In C#, foreach statement provides a convenient way of iterating an enumerable object. foreach iterates an element in an enumerable object one by one.

But then, a question popped up. What happens when we use "foreach" multiple times against the same enumerable object? Below is a sample code that used foreach twice.

In the first foreach (in Print() method), I intentionally added a "break" statement to break out of the loop after displaying first element. In the second foreach, it iterates all of the elements.

So the question is "will the 2nd foreach continue from the previous iteration point (which is from 2nd element of data) OR will it start over again from the 1st element?"

class Program
{
    static void Main(string[] args)
    {
        var n = GetNumber();
        Print(n);
    }

    static void Print(IEnumerable data)
    {     
        // 1st foreach against IEnumerable  
        foreach (var item in data)
        {
            Console.WriteLine(item);
            break;
        }
        
        // 2nd foreach against the same IEnumerable
        foreach (var item in data)
        {
            Console.WriteLine(item);
        }
    }
    
    static IEnumerable GetNumber()
    {
        yield return 1;
        yield return 2;
        yield return 3;
    }
}    

The correct answer is every "foreach" will restart the iteration all over again. So the result of the above code will be "1 1 2 3" instead of "1 2 3."

foreach gets new enumerator from the IEnumerable object every time it starts loop. This behavior is little different from Python. If you run the below Python program, you will get "1 2 3" since "for" statement in Python is using current iterator instead of creating new iterator.

    
def getNumber():
    yield 1
    yield 2
    yield 3

def printData(data):
    for n in data:
        print(n)
        break
    for n in data:
        print(n)

g = getNumber()
printData(g)