Skip to content

Instantly share code, notes, and snippets.

@bbarry
Last active March 30, 2017 21:50
Show Gist options
  • Select an option

  • Save bbarry/d297191af0945168f13b39ddb13e9d13 to your computer and use it in GitHub Desktop.

Select an option

Save bbarry/d297191af0945168f13b39ddb13e9d13 to your computer and use it in GitHub Desktop.
public struct Arguments<T> : IReadOnlyList<T>
{
readonly T _arg1, _arg2, _arg3;
readonly IEnumerable<T> _enumerable;
readonly int _count;
public Arguments(T arg1) => (_arg1, _arg2, _arg3, _enumerable, _count)
= (arg1, default(T), default(T), null, 1);
public Arguments(T arg1, T arg2) => (_arg1, _arg2, _arg3, _enumerable, _count)
= (arg1, arg2, default(T), null, 2);
public Arguments(T arg1, T arg2, T arg3) => (_arg1, _arg2, _arg3, _enumerable, _count)
= (arg1, arg2, arg3, null, 3);
public Arguments(IEnumerable<T> enumerable) => (_arg1, _arg2, _arg3, _enumerable, _count)
= (default(T), default(T), default(T), enumerable, -1);
public Arguments(params T[] enumerable) => (_arg1, _arg2, _arg3, _enumerable, _count)
= (default(T), default(T), default(T), enumerable, -1);
public T this[int index]
{
get
{
if ((uint)index >= (uint)_count) throw new IndexOutOfRangeException();
if ((uint)_count < 3u)
{
switch (index)
{
case 0:
return _arg1;
case 1:
return _arg2;
default:
return _arg3;
}
}
var l = _enumerable as IReadOnlyList<T>;
if (l != null) return l[index];
var l2 = _enumerable as IList<T>;
if (l2 != null) return l2[index];
return _enumerable.ElementAt(index);
}
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
IEnumerator<T> IEnumerable<T>.GetEnumerator() => GetEnumerator();
public Enumerator GetEnumerator() => new Enumerator(this);
public int Count => _count;
public struct Enumerator : IEnumerator<T>
{
private Arguments<T> _this;
private int _state;
private T _current;
private readonly IEnumerator<T> _enumerator;
public Enumerator(Arguments<T> @this)
{
_this = @this;
_enumerator = @this._enumerable?.GetEnumerator(); ;
_state = _enumerator == null ? -1 : -2;
_current = default(T);
}
public T Current => _current;
public bool MoveNext()
{
switch (_state)
{
case -2:
var n = _enumerator.MoveNext();
if (n)
{
_current = _enumerator.Current;
}
else
{
_current = default(T);
_state = -3;
}
return n;
case -1:
_state = 0;
_current = _this._arg1;
return _this._count > 0;
case 0:
_state = 1;
_current = _this._arg2;
return _this._count > 1;
case 1:
_state = 2;
_current = _this._arg3;
return _this._count > 2;
default:
_state = -3;
return false;
}
}
void IEnumerator.Reset() => _enumerator?.Reset();
object IEnumerator.Current => _current;
void IDisposable.Dispose() => _enumerator?.Dispose();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment