Skip to content

Instantly share code, notes, and snippets.

@jeremysimmons
Created October 18, 2022 14:33
Show Gist options
  • Save jeremysimmons/545de72e0447c55b9ae5ede910d5129b to your computer and use it in GitHub Desktop.
Save jeremysimmons/545de72e0447c55b9ae5ede910d5129b to your computer and use it in GitHub Desktop.
Enumerable With Metadata
public static class IndexedEnumerable
{
public static IndexedEnumerable<T> AsIndexedEnumerable<T>(this IEnumerable<T> source)
{
return Create(source);
}
public static IndexedEnumerable<T> Create<T>(IEnumerable<T> source)
{
return new IndexedEnumerable<T>(source);
}
}
public class IndexedEnumerable<T> : IEnumerable<IndexedEnumerable<T>.EntryItem>, IEnumerable
{
private readonly IEnumerable<T> _enumerable;
/// <summary>
/// Default constructor.
/// </summary>
private IndexedEnumerable()
{
}
/// <summary>
/// Constructor that takes an IEnumerable&lt;T&gt;
/// </summary>
/// <param name="enumerable">The collection to enumerate.</param>
public IndexedEnumerable(IEnumerable<T> enumerable)
{
if (enumerable == null)
{
throw new ArgumentNullException("enumerable");
}
this._enumerable = enumerable;
}
/// <summary>
/// Returns an enumeration of Entry objects.
/// </summary>
public IEnumerator<IndexedEnumerable<T>.EntryItem> GetEnumerator()
{
using IEnumerator<T> enumerator = _enumerable.GetEnumerator();
if (enumerator.MoveNext())
{
int index = 0;
bool first = true;
bool isLast = false;
while (!isLast)
{
T current = enumerator.Current;
int currentIndex = index;
isLast = !enumerator.MoveNext();
index = currentIndex + 1;
yield return new EntryItem(first, isLast, current, currentIndex);
first = false;
}
}
}
/// <summary>Non-generic form of GetEnumerator.</summary>
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
/// <summary>
/// Represents each entry returned within a collection,
/// containing the _value and whether it is the first and/or
/// the last entry in the collection's. enumeration
/// </summary>
public class EntryItem
{
/// <summary>
/// The index of the current item in the collection.
/// </summary>
public int Index
{
get;
internal set;
}
/// <summary>
/// Returns true if the current item has an even index
/// </summary>
public bool IsEven
{
get;
internal set;
}
/// <summary>
/// Returns true if it is the first item in the collection.
/// </summary>
public bool IsFirst
{
get;
internal set;
}
/// <summary>
/// Returns true if it is the last item in the collection.
/// </summary>
public bool IsLast
{
get;
internal set;
}
/// <summary>
/// Returns true if the current item has an odd index
/// </summary>
public bool IsOdd
{
get;
internal set;
}
/// <summary>
/// The Entry Value.
/// </summary>
public T Value
{
get;
internal set;
}
internal EntryItem()
{
}
internal EntryItem(bool isFirst, bool isLast, T value, int index)
{
this.IsFirst = isFirst;
this.IsLast = isLast;
this.Value = value;
this.Index = index;
this.IsEven = index % 2 == 0;
this.IsOdd = !this.IsEven;
}
public static implicit operator T(IndexedEnumerable<T>.EntryItem item)
{
return item.Value;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment