Deep Dive into IEnumerable and IEnumerator in C#

Nov 23, 2025 · Programming · 8 views · 7.8

Keywords: C# | IEnumerable | IEnumerator | Iteration Interfaces | Collection Operations

Abstract: This article provides a comprehensive analysis of the IEnumerable and IEnumerator interfaces in C#, covering their core concepts, implementation principles, and practical applications. By examining the compilation mechanism of foreach loops, it explains the roles of these interfaces in the iteration process and offers implementation examples for custom collection classes. The article also compares different implementation approaches to help developers understand the internal mechanics of .NET collection iteration.

Fundamental Concepts of IEnumerable and IEnumerator

In the C# programming language, IEnumerable and IEnumerator are core interfaces that support collection iteration. Understanding the relationship between these two interfaces is crucial for mastering .NET collection operations.

Interface Definitions and Relationships

The IEnumerable interface defines a single method:

IEnumerator GetEnumerator()

This method returns an object that implements the IEnumerator interface. The IEnumerator interface contains three key members:

bool MoveNext()
object Current { get; }
void Reset()

Internal Mechanism of foreach Loops

Many developers mistakenly believe that foreach is a syntax sugar independent of these interfaces. In reality, when the compiler encounters a foreach statement, it transforms it into equivalent code based on IEnumerator.

Consider the following foreach example:

foreach (Foo bar in baz)
{
    // Loop body
}

The compiler transforms this into:

IEnumerator bat = baz.GetEnumerator();
while (bat.MoveNext())
{
    Foo bar = (Foo)bat.Current;
    // Loop body
}

Implementing Custom Iterable Classes

To enable custom classes to support foreach iteration, the IEnumerable interface must be implemented. Here's an example implementation of a car garage class:

using System.Collections;

public class Garage : IEnumerable
{
    private Car[] carArray = new Car[4];
    
    public Garage()
    {
        carArray[0] = new Car("Rusty", 30);
        carArray[1] = new Car("Clunker", 55);
        carArray[2] = new Car("Zippy", 30);
        carArray[3] = new Car("Fred", 30);
    }
    
    public IEnumerator GetEnumerator()
    {
        return carArray.GetEnumerator();
    }
}

Explicit Interface Implementation

To hide the GetEnumerator method from object-level visibility, explicit interface implementation can be used:

IEnumerator IEnumerable.GetEnumerator()
{
    return carArray.GetEnumerator();
}

This approach ensures that foreach continues to work properly while preventing ordinary object users from directly accessing the enumerator method.

Manual Usage of IEnumerator

Beyond automatic handling by foreach, developers can also manipulate IEnumerator directly:

IEnumerator i = carLot.GetEnumerator();
i.MoveNext();
Car myCar = (Car)i.Current;
Console.WriteLine("{0} is going {1} MPH", myCar.PetName, myCar.CurrentSpeed);

Practical Application Scenarios

IEnumerable and IEnumerator are particularly useful in the following scenarios:

Conclusion

IEnumerable and IEnumerator form the foundational framework for collection iteration in C#. Understanding their internal workings not only facilitates proper usage of existing collection types but also provides the necessary foundation for creating custom iterable classes. Through appropriate implementation of these interfaces, developers can create custom collection types that integrate seamlessly with the .NET ecosystem.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.