Skip to content

Instantly share code, notes, and snippets.

@IEvangelist
Last active August 31, 2020 12:37
Show Gist options
  • Save IEvangelist/d4fb5ad70652a3d8918816d62217323b to your computer and use it in GitHub Desktop.
Save IEvangelist/d4fb5ad70652a3d8918816d62217323b to your computer and use it in GitHub Desktop.
public readonly struct EnumerableRange : IEnumerable<int>
{
readonly Range _range;
public EnumerableRange(Range range)
{
if (range.Start.IsFromEnd || range.End.IsFromEnd)
{
throw new ArgumentException(nameof(range));
}
_range = range;
}
public static implicit operator EnumerableRange(Range range) => new EnumerableRange(range);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
IEnumerator<int> IEnumerable<int>.GetEnumerator() => GetEnumerator();
// Important to return RangeEnumerator, not IEnumerable<int> here, or foreach would box the struct
public RangeEnumerator GetEnumerator() => new RangeEnumerator(_range);
public override string ToString() => _range.ToString();
public struct RangeEnumerator : IEnumerator<int>, IEnumerator
{
public int Current => _range.Start.Value + (_isAscending ? _index : -_index);
object IEnumerator.Current => Current;
int _index;
readonly Range _range;
readonly bool _isAscending;
internal RangeEnumerator(Range range)
{
_index = -1;
_range = range;
_isAscending = _range.Start.Value < _range.End.Value;
}
public bool MoveNext()
{
if (_index + 1 >= Math.Abs(_range.End.Value - _range.Start.Value))
{
return false;
}
_index++;
return true;
}
public void Reset() => _index = 0;
public void Dispose() { }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment