Blog

Filter posts by Category Or Tag of the Blog section!

Implementing Custom IEnumerable without yield

Monday, 04 July 2022

There is a way of implementing yield of C# with a collection. As an example, take a look at the following method:

 

public IEnumerable<int> GetNumbersWithCollection()
{
    List<int> numbers = new List<int>();
    
    for (int i = 1; i <= 5; i++)
    {
        numbers.Add(i);
    }
    
    return numbers; // Returning the list
}


 

we can easily use yield like this:

 

public IEnumerable<int> GetNumbersWithYield()
{
    for (int i = 1; i <= 5; i++)
    {
        yield return i;
    }
}


 

yield is often used to lazily return elements of a collection one at a time, without creating the entire collection in memory at once.  To mimic the behavior of yield manually, you can implement IEnumerable<T> and IEnumerator<T> interfaces in your class. This allows you to control the iteration logic and return elements step by step, just like yield would.

This class will handle the iteration state, keeping track of the current item and progressing to the next.



 

public class NumberEnumerator : IEnumerator<int>
{
    private int _current = 0;
    private int _max = 5;

    // Returns the current element
    public int Current => _current;

    // This is required by IEnumerator, though we don't use it here
    object System.Collections.IEnumerator.Current => _current;

    // Move to the next element
    public bool MoveNext()
    {
        if (_current < _max)
        {
            _current++;
            return true;
        }
        return false;
    }

    // Reset the enumerator to its initial position
    public void Reset()
    {
        _current = 0;
    }

    // Dispose of any resources (none needed in this case)
    public void Dispose() { }
}


And This class will provide the GetEnumerator() method, which returns our custom IEnumerator.


 

public class NumberCollection : IEnumerable<int>
{
    public IEnumerator<int> GetEnumerator()
    {
        return new NumberEnumerator();
    }

    // Non-generic version required by IEnumerable
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}


 

Using yield when you want to generate elements lazily and avoid holding the entire collection in memory is too helpful. But in some cases you may need to create your own. Cases like these: 

  • More control over the iteration process (for example, adding custom logic for each iteration step).
  • Useful when working with complex state machines or advanced iteration logic.

 

Category: Software

Tags: C#

comments powered by Disqus