An enumerable for seeing if I'm at the first or last part of a loop

Tag: Csharp
Edit
Created: 2021/1/15
Updated: 2024/7/26

Prettier, with syntax highlighting at https://gist.github.com/yumaikas/71c9c35a85484f49484350cff8dd1c6e
Assembled in response to this tweet: https://mobile.twitter.com/ereliuer_eteer/status/1349897779158548481

@ereliuer_eteer: I wish in a foreach loop I could tell if the current iteration is the last one.

Code to see if I’m at the first/middle/last part of an IEnumerable<T>. Right now, you can run the code snippet below as a LinqPad script, or copy it into a greater C# program and use as needed.

void Main()
{
     LoopStatus(new int[]{ 1, 2, 3, 4, 5 }).Dump();
}

// Define other methods and classes here

public enum Iteration { 
    First,
    Middle,
    Last,
}
public struct IterationPostition<T> { 
    public Iteration Iteration {get; private set;}
    public T Value {get; private set;}
    public IterationPostition(Iteration iter, T value)
    {
        Value = value;
        Iteration = iter;
    }
}

public IEnumerable<IterationPostition<T>> LoopStatus<T>(IEnumerable<T> innerIterator) {
    var enumerator =  innerIterator.GetEnumerator();

    bool hasMoreItems = false;
    T prev = default(T);
    Iteration state = Iteration.First;
    while (true)
    {
        switch (state) {
        
            case Iteration.First:
            hasMoreItems = enumerator.MoveNext();
            yield return new IterationPostition<T>(Iteration.First, enumerator.Current);
            hasMoreItems = enumerator.MoveNext();
            prev = enumerator.Current;
            state = Iteration.Middle;
            break;
            
            case Iteration.Middle:
            hasMoreItems = enumerator.MoveNext();
            if (hasMoreItems) {
                yield return new IterationPostition<T>(Iteration.Middle, prev);
                prev = enumerator.Current;
            } else {
                yield return new IterationPostition<T>(Iteration.Last, prev);
                state = Iteration.Last;
            }
            break;
            
            case Iteration.Last:
            yield break;
            
        }
    }
}