Created
October 18, 2022 14:33
-
-
Save jeremysimmons/545de72e0447c55b9ae5ede910d5129b to your computer and use it in GitHub Desktop.
Enumerable With Metadata
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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<T> | |
/// </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