Understanding IEnumerable in C#: The Foundation of LINQ


If you’ve ever used a foreach loop in C#, you’ve already been using IEnumerable.

It’s one of the most fundamental interfaces in .NET and forms the foundation of LINQ.




What is IEnumerable?

IEnumerable represents a sequence of elements that you can iterate over, one by one.

It powers the foreach loop.

var numbers = new List<int> { 1, 2, 3 };

foreach (var n in numbers)
{
    Console.WriteLine(n);
}
Enter fullscreen mode

Exit fullscreen mode

Behind the scenes, foreach calls GetEnumerator(), which returns an iterator.




The Interface Definition

Here’s the simplified definition of IEnumerable:

public interface IEnumerable<out T>
{
    IEnumerator<T> GetEnumerator();
}
Enter fullscreen mode

Exit fullscreen mode

It’s surprisingly simple. It just promises that any type implementing it can return an IEnumerator.

And what’s IEnumerator? It’s another interface that knows how to move through a sequence:

public interface IEnumerator<T> : IDisposable
{
    T Current { get; }
    bool MoveNext();
    void Reset(); // rarely used in practice
}
Enter fullscreen mode

Exit fullscreen mode




Iterating Without foreach

Since foreach is just syntactic shortcut, you can do the same manually:

var numbers = new List<int> { 1, 2, 3 };
var enumerator = numbers.GetEnumerator();

while (enumerator.MoveNext())
{
    var current = enumerator.Current;
    Console.WriteLine(current);
}
Enter fullscreen mode

Exit fullscreen mode




Custom Implementation Example

You can also implement IEnumerable yourself.

Here’s a simple example that generates even numbers up to a maximum value:

public class EvenNumbers(int last) : IEnumerable<int>
{
    public class EvenNumber(int last) : IEnumerator<int>
    {
        private int _current = -2;

        public bool MoveNext()
        {
            _current += 2;
            return _current <= last;
        }

        public void Reset() => _current = -2;
        int IEnumerator<int>.Current => _current;
        object? System.Collections.IEnumerator.Current => _current;
        public void Dispose() { }
    }

    public IEnumerator<int> GetEnumerator() => new EvenNumber(last);
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => this.GetEnumerator();
}
Enter fullscreen mode

Exit fullscreen mode

Usage:

var evens = new EvenNumbers(10);

foreach (var e in evens)
    Console.WriteLine(e);
// Output: 0, 2, 4, 6, 8, 10
Enter fullscreen mode

Exit fullscreen mode

Notice that the _current always starts in an invalid position and has the right value after the first call of MoveNext().




Why is it Important?

LINQ methods like .Where(), .Select(), and .OrderBy() all extend IEnumerable.

Without it, LINQ wouldn’t exist.

Example:

var numbers = Enumerable.Range(1, 5);  
var squared = numbers.Select(x => x * x);

Console.WriteLine(string.Join(", ", squared));
// Output: 1, 4, 9, 16, 25
Enter fullscreen mode

Exit fullscreen mode




Deferred Execution

A powerful feature of IEnumerable is deferred execution.

LINQ queries aren’t run immediately, they’re only executed when you iterate.

var numbers = Enumerable.Range(1, 5);
var query = numbers.Where(n => n % 2 == 0);

// Nothing happens yet!

foreach (var n in query)
    Console.WriteLine(n); // Execution happens here
Enter fullscreen mode

Exit fullscreen mode

This allows efficient chaining of operations without unnecessary work.




Performance Notes

  • IEnumerable only supports forward iteration.
    You can’t access items by index or know the count without iterating.
  • For random access or collection size, use ICollection or IList.
  • Best suited for streaming data and large sequences where you don’t want everything in memory at once.



Key Takeaways

  • IEnumerable defines the contract for iteration in C#.
  • It powers foreach and enables LINQ.
  • IEnumerator drives iteration with MoveNext() and Current.
  • LINQ queries on IEnumerable use deferred execution.
  • For advanced operations like indexing, prefer IList or ICollection.

āœ… That’s all, folks!

šŸ’¬ Let’s Connect

Have any questions, suggestions for improvement, or just want to share your thoughts?

Feel free to leave a comment here, or get in touch with me directly on LinkedIn — I’d love to connect!



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *