Last active
March 30, 2017 21:50
-
-
Save bbarry/d297191af0945168f13b39ddb13e9d13 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 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