Enumerable.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / Linq / Enumerable.cs / 1407647 / Enumerable.cs

                            using System; 
using System.Collections;
using System.Collections.Generic;
using System.Threading;
 
// Include Silverlight's managed resources
#if SILVERLIGHT 
using System.Core; 
#endif //SILVERLIGHT
 
namespace System.Linq
{
    public static class Enumerable
    { 
        public static IEnumerable Where(this IEnumerable source, Func predicate) {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (predicate == null) throw Error.ArgumentNull("predicate"); 
            if (source is Iterator) return ((Iterator)source).Where(predicate);
            if (source is TSource[]) return new WhereArrayIterator((TSource[])source, predicate); 
            if (source is List) return new WhereListIterator((List)source, predicate);
            return new WhereEnumerableIterator(source, predicate);
        }
 
        public static IEnumerable Where(this IEnumerable source, Func predicate) {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (predicate == null) throw Error.ArgumentNull("predicate"); 
            return WhereIterator(source, predicate);
        } 

        static IEnumerable WhereIterator(IEnumerable source, Func predicate) {
            int index = -1;
            foreach (TSource element in source) { 
                checked { index++; }
                if (predicate(element, index)) yield return element; 
            } 
        }
 
        public static IEnumerable Select(this IEnumerable source, Func selector) {
            if (source == null) throw Error.ArgumentNull("source");
            if (selector == null) throw Error.ArgumentNull("selector");
            if (source is Iterator) return ((Iterator)source).Select(selector); 
            if (source is TSource[]) return new WhereSelectArrayIterator((TSource[])source, null, selector);
            if (source is List) return new WhereSelectListIterator((List)source, null, selector); 
            return new WhereSelectEnumerableIterator(source, null, selector); 
        }
 
        public static IEnumerable Select(this IEnumerable source, Func selector) {
            if (source == null) throw Error.ArgumentNull("source");
            if (selector == null) throw Error.ArgumentNull("selector");
            return SelectIterator(source, selector); 
        }
 
        static IEnumerable SelectIterator(IEnumerable source, Func selector) { 
            int index = -1;
            foreach (TSource element in source) { 
                checked { index++; }
                yield return selector(element, index);
            }
        } 

        static Func CombinePredicates(Func predicate1, Func predicate2) { 
            return x => predicate1(x) && predicate2(x); 
        }
 
        static Func CombineSelectors(Func selector1, Func selector2) {
            return x => selector2(selector1(x));
        }
 
        abstract class Iterator : IEnumerable, IEnumerator
        { 
            int threadId; 
            internal int state;
            internal TSource current; 

            public Iterator() {
                threadId = Thread.CurrentThread.ManagedThreadId;
            } 

            public TSource Current { 
                get { return current; } 
            }
 
            public abstract Iterator Clone();

            public virtual void Dispose() {
                current = default(TSource); 
                state = -1;
            } 
 
            public IEnumerator GetEnumerator() {
                if (threadId == Thread.CurrentThread.ManagedThreadId && state == 0) { 
                    state = 1;
                    return this;
                }
                Iterator duplicate = Clone(); 
                duplicate.state = 1;
                return duplicate; 
            } 

            public abstract bool MoveNext(); 

            public abstract IEnumerable Select(Func selector);

            public abstract IEnumerable Where(Func predicate); 

            object IEnumerator.Current { 
                get { return Current; } 
            }
 
            IEnumerator IEnumerable.GetEnumerator() {
                return GetEnumerator();
            }
 
            void IEnumerator.Reset() {
                throw new NotImplementedException(); 
            } 
        }
 
        class WhereEnumerableIterator : Iterator
        {
            IEnumerable source;
            Func predicate; 
            IEnumerator enumerator;
 
            public WhereEnumerableIterator(IEnumerable source, Func predicate) { 
                this.source = source;
                this.predicate = predicate; 
            }

            public override Iterator Clone() {
                return new WhereEnumerableIterator(source, predicate); 
            }
 
            public override void Dispose() { 
                if (enumerator is IDisposable) ((IDisposable)enumerator).Dispose();
                enumerator = null; 
                base.Dispose();
            }

            public override bool MoveNext() { 
                switch (state) {
                    case 1: 
                        enumerator = source.GetEnumerator(); 
                        state = 2;
                        goto case 2; 
                    case 2:
                        while (enumerator.MoveNext()) {
                            TSource item = enumerator.Current;
                            if (predicate(item)) { 
                                current = item;
                                return true; 
                            } 
                        }
                        Dispose(); 
                        break;
                }
                return false;
            } 

            public override IEnumerable Select(Func selector) { 
                return new WhereSelectEnumerableIterator(source, predicate, selector); 
            }
 
            public override IEnumerable Where(Func predicate) {
                return new WhereEnumerableIterator(source, CombinePredicates(this.predicate, predicate));
            }
        } 

        class WhereArrayIterator : Iterator 
        { 
            TSource[] source;
            Func predicate; 
            int index;

            public WhereArrayIterator(TSource[] source, Func predicate) {
                this.source = source; 
                this.predicate = predicate;
            } 
 
            public override Iterator Clone() {
                return new WhereArrayIterator(source, predicate); 
            }

            public override bool MoveNext() {
                if (state == 1) { 
                    while (index < source.Length) {
                        TSource item = source[index]; 
                        index++; 
                        if (predicate(item)) {
                            current = item; 
                            return true;
                        }
                    }
                    Dispose(); 
                }
                return false; 
            } 

            public override IEnumerable Select(Func selector) { 
                return new WhereSelectArrayIterator(source, predicate, selector);
            }

            public override IEnumerable Where(Func predicate) { 
                return new WhereArrayIterator(source, CombinePredicates(this.predicate, predicate));
            } 
        } 

        class WhereListIterator : Iterator 
        {
            List source;
            Func predicate;
            List.Enumerator enumerator; 

            public WhereListIterator(List source, Func predicate) { 
                this.source = source; 
                this.predicate = predicate;
            } 

            public override Iterator Clone() {
                return new WhereListIterator(source, predicate);
            } 

            public override bool MoveNext() { 
                switch (state) { 
                    case 1:
                        enumerator = source.GetEnumerator(); 
                        state = 2;
                        goto case 2;
                    case 2:
                        while (enumerator.MoveNext()) { 
                            TSource item = enumerator.Current;
                            if (predicate(item)) { 
                                current = item; 
                                return true;
                            } 
                        }
                        Dispose();
                        break;
                } 
                return false;
            } 
 
            public override IEnumerable Select(Func selector) {
                return new WhereSelectListIterator(source, predicate, selector); 
            }

            public override IEnumerable Where(Func predicate) {
                return new WhereListIterator(source, CombinePredicates(this.predicate, predicate)); 
            }
        } 
 
        class WhereSelectEnumerableIterator : Iterator
        { 
            IEnumerable source;
            Func predicate;
            Func selector;
            IEnumerator enumerator; 

            public WhereSelectEnumerableIterator(IEnumerable source, Func predicate, Func selector) { 
                this.source = source; 
                this.predicate = predicate;
                this.selector = selector; 
            }

            public override Iterator Clone() {
                return new WhereSelectEnumerableIterator(source, predicate, selector); 
            }
 
            public override void Dispose() { 
                if (enumerator is IDisposable) ((IDisposable)enumerator).Dispose();
                enumerator = null; 
                base.Dispose();
            }

            public override bool MoveNext() { 
                switch (state) {
                    case 1: 
                        enumerator = source.GetEnumerator(); 
                        state = 2;
                        goto case 2; 
                    case 2:
                        while (enumerator.MoveNext()) {
                            TSource item = enumerator.Current;
                            if (predicate == null || predicate(item)) { 
                                current = selector(item);
                                return true; 
                            } 
                        }
                        Dispose(); 
                        break;
                }
                return false;
            } 

            public override IEnumerable Select(Func selector) { 
                return new WhereSelectEnumerableIterator(source, predicate, CombineSelectors(this.selector, selector)); 
            }
 
            public override IEnumerable Where(Func predicate) {
                return new WhereEnumerableIterator(this, predicate);
            }
        } 

        class WhereSelectArrayIterator : Iterator 
        { 
            TSource[] source;
            Func predicate; 
            Func selector;
            int index;

            public WhereSelectArrayIterator(TSource[] source, Func predicate, Func selector) { 
                this.source = source;
                this.predicate = predicate; 
                this.selector = selector; 
            }
 
            public override Iterator Clone() {
                return new WhereSelectArrayIterator(source, predicate, selector);
            }
 
            public override bool MoveNext() {
                if (state == 1) { 
                    while (index < source.Length) { 
                        TSource item = source[index];
                        index++; 
                        if (predicate == null || predicate(item)) {
                            current = selector(item);
                            return true;
                        } 
                    }
                    Dispose(); 
                } 
                return false;
            } 

            public override IEnumerable Select(Func selector) {
                return new WhereSelectArrayIterator(source, predicate, CombineSelectors(this.selector, selector));
            } 

            public override IEnumerable Where(Func predicate) { 
                return new WhereEnumerableIterator(this, predicate); 
            }
        } 

        class WhereSelectListIterator : Iterator
        {
            List source; 
            Func predicate;
            Func selector; 
            List.Enumerator enumerator; 

            public WhereSelectListIterator(List source, Func predicate, Func selector) { 
                this.source = source;
                this.predicate = predicate;
                this.selector = selector;
            } 

            public override Iterator Clone() { 
                return new WhereSelectListIterator(source, predicate, selector); 
            }
 
            public override bool MoveNext() {
                switch (state) {
                    case 1:
                        enumerator = source.GetEnumerator(); 
                        state = 2;
                        goto case 2; 
                    case 2: 
                        while (enumerator.MoveNext()) {
                            TSource item = enumerator.Current; 
                            if (predicate == null || predicate(item)) {
                                current = selector(item);
                                return true;
                            } 
                        }
                        Dispose(); 
                        break; 
                }
                return false; 
            }

            public override IEnumerable Select(Func selector) {
                return new WhereSelectListIterator(source, predicate, CombineSelectors(this.selector, selector)); 
            }
 
            public override IEnumerable Where(Func predicate) { 
                return new WhereEnumerableIterator(this, predicate);
            } 
        }

        //public static IEnumerable Where(this IEnumerable source, Func predicate) {
        //    if (source == null) throw Error.ArgumentNull("source"); 
        //    if (predicate == null) throw Error.ArgumentNull("predicate");
        //    return WhereIterator(source, predicate); 
        //} 

        //static IEnumerable WhereIterator(IEnumerable source, Func predicate) { 
        //    foreach (TSource element in source) {
        //        if (predicate(element)) yield return element;
        //    }
        //} 

        //public static IEnumerable Select(this IEnumerable source, Func selector) { 
        //    if (source == null) throw Error.ArgumentNull("source"); 
        //    if (selector == null) throw Error.ArgumentNull("selector");
        //    return SelectIterator(source, selector); 
        //}

        //static IEnumerable SelectIterator(IEnumerable source, Func selector) {
        //    foreach (TSource element in source) { 
        //        yield return selector(element);
        //    } 
        //} 

        public static IEnumerable SelectMany(this IEnumerable source, Func> selector) { 
            if (source == null) throw Error.ArgumentNull("source");
            if (selector == null) throw Error.ArgumentNull("selector");
            return SelectManyIterator(source, selector);
        } 

        static IEnumerable SelectManyIterator(IEnumerable source, Func> selector) { 
            foreach (TSource element in source) { 
                foreach (TResult subElement in selector(element)) {
                    yield return subElement; 
                }
            }
        }
 
        public static IEnumerable SelectMany(this IEnumerable source, Func> selector) {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (selector == null) throw Error.ArgumentNull("selector"); 
            return SelectManyIterator(source, selector);
        } 

        static IEnumerable SelectManyIterator(IEnumerable source, Func> selector) {
            int index = -1;
            foreach (TSource element in source) { 
                checked { index++; }
                foreach (TResult subElement in selector(element, index)) { 
                    yield return subElement; 
                }
            } 
        }
        public static IEnumerable SelectMany(this IEnumerable source, Func> collectionSelector, Func resultSelector)
        {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (collectionSelector == null) throw Error.ArgumentNull("collectionSelector");
            if (resultSelector == null) throw Error.ArgumentNull("resultSelector"); 
            return SelectManyIterator(source, collectionSelector, resultSelector); 
        }
 
        static IEnumerable SelectManyIterator(IEnumerable source, Func> collectionSelector, Func resultSelector){
            int index = -1;
            foreach (TSource element in source){
                checked { index++; } 
                foreach (TCollection subElement in collectionSelector(element, index)){
                    yield return resultSelector(element, subElement); 
                } 
            }
        } 

        public static IEnumerable SelectMany(this IEnumerable source, Func> collectionSelector, Func resultSelector) {
            if (source == null) throw Error.ArgumentNull("source");
            if (collectionSelector == null) throw Error.ArgumentNull("collectionSelector"); 
            if (resultSelector == null) throw Error.ArgumentNull("resultSelector");
            return SelectManyIterator(source, collectionSelector, resultSelector); 
        } 

        static IEnumerable SelectManyIterator(IEnumerable source, Func> collectionSelector, Func resultSelector) { 
            foreach (TSource element in source) {
                foreach (TCollection subElement in collectionSelector(element)) {
                    yield return resultSelector(element, subElement);
                } 
            }
        } 
 
        public static IEnumerable Take(this IEnumerable source, int count) {
            if (source == null) throw Error.ArgumentNull("source"); 
            return TakeIterator(source, count);
        }

        static IEnumerable TakeIterator(IEnumerable source, int count) { 
            if (count > 0) {
                foreach (TSource element in source) { 
                    yield return element; 
                    if (--count == 0) break;
                } 
            }
        }

        public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) { 
            if (source == null) throw Error.ArgumentNull("source");
            if (predicate == null) throw Error.ArgumentNull("predicate"); 
            return TakeWhileIterator(source, predicate); 
        }
 
        static IEnumerable TakeWhileIterator(IEnumerable source, Func predicate) {
            foreach (TSource element in source) {
                if (!predicate(element)) break;
                yield return element; 
            }
        } 
 
        public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (predicate == null) throw Error.ArgumentNull("predicate");
            return TakeWhileIterator(source, predicate);
        }
 
        static IEnumerable TakeWhileIterator(IEnumerable source, Func predicate) {
            int index = -1; 
            foreach (TSource element in source) { 
                checked { index++; }
                if (!predicate(element, index)) break; 
                yield return element;
            }
        }
 
        public static IEnumerable Skip(this IEnumerable source, int count) {
            if (source == null) throw Error.ArgumentNull("source"); 
            return SkipIterator(source, count); 
        }
 
        static IEnumerable SkipIterator(IEnumerable source, int count) {
            using (IEnumerator e = source.GetEnumerator()) {
                while (count > 0 && e.MoveNext()) count--;
                if (count <= 0) { 
                    while (e.MoveNext()) yield return e.Current;
                } 
            } 
        }
 
        public static IEnumerable SkipWhile(this IEnumerable source, Func predicate) {
            if (source == null) throw Error.ArgumentNull("source");
            if (predicate == null) throw Error.ArgumentNull("predicate");
            return SkipWhileIterator(source, predicate); 
        }
 
        static IEnumerable SkipWhileIterator(IEnumerable source, Func predicate) { 
            bool yielding = false;
            foreach (TSource element in source) { 
                if (!yielding && !predicate(element)) yielding = true;
                if (yielding) yield return element;
            }
        } 

        public static IEnumerable SkipWhile(this IEnumerable source, Func predicate) { 
            if (source == null) throw Error.ArgumentNull("source"); 
            if (predicate == null) throw Error.ArgumentNull("predicate");
            return SkipWhileIterator(source, predicate); 
        }

        static IEnumerable SkipWhileIterator(IEnumerable source, Func predicate) {
            int index = -1; 
            bool yielding = false;
            foreach (TSource element in source) { 
                checked { index++; } 
                if (!yielding && !predicate(element, index)) yielding = true;
                if (yielding) yield return element; 
            }
        }

        public static IEnumerable Join(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector) { 
            if (outer == null) throw Error.ArgumentNull("outer");
            if (inner == null) throw Error.ArgumentNull("inner"); 
            if (outerKeySelector == null) throw Error.ArgumentNull("outerKeySelector"); 
            if (innerKeySelector == null) throw Error.ArgumentNull("innerKeySelector");
            if (resultSelector == null) throw Error.ArgumentNull("resultSelector"); 
            return JoinIterator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
        }

        public static IEnumerable Join(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector, IEqualityComparer comparer) { 
            if (outer == null) throw Error.ArgumentNull("outer");
            if (inner == null) throw Error.ArgumentNull("inner"); 
            if (outerKeySelector == null) throw Error.ArgumentNull("outerKeySelector"); 
            if (innerKeySelector == null) throw Error.ArgumentNull("innerKeySelector");
            if (resultSelector == null) throw Error.ArgumentNull("resultSelector"); 
            return JoinIterator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
        }

        static IEnumerable JoinIterator(IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector, IEqualityComparer comparer) { 
            Lookup lookup = Lookup.CreateForJoin(inner, innerKeySelector, comparer);
            foreach (TOuter item in outer) { 
                Lookup.Grouping g = lookup.GetGrouping(outerKeySelector(item), false); 
                if (g != null) {
                    for (int i = 0; i < g.count; i++) { 
                        yield return resultSelector(item, g.elements[i]);
                    }
                }
            } 
        }
 
        public static IEnumerable GroupJoin(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector) { 
            if (outer == null) throw Error.ArgumentNull("outer");
            if (inner == null) throw Error.ArgumentNull("inner"); 
            if (outerKeySelector == null) throw Error.ArgumentNull("outerKeySelector");
            if (innerKeySelector == null) throw Error.ArgumentNull("innerKeySelector");
            if (resultSelector == null) throw Error.ArgumentNull("resultSelector");
            return GroupJoinIterator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, null); 
        }
 
        public static IEnumerable GroupJoin(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector, IEqualityComparer comparer) { 
            if (outer == null) throw Error.ArgumentNull("outer");
            if (inner == null) throw Error.ArgumentNull("inner"); 
            if (outerKeySelector == null) throw Error.ArgumentNull("outerKeySelector");
            if (innerKeySelector == null) throw Error.ArgumentNull("innerKeySelector");
            if (resultSelector == null) throw Error.ArgumentNull("resultSelector");
            return GroupJoinIterator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer); 
        }
 
        static IEnumerable GroupJoinIterator(IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector, IEqualityComparer comparer) { 
            Lookup lookup = Lookup.CreateForJoin(inner, innerKeySelector, comparer);
            foreach (TOuter item in outer) { 
                yield return resultSelector(item, lookup[outerKeySelector(item)]);
            }
        }
 
        public static IOrderedEnumerable OrderBy(this IEnumerable source, Func keySelector) {
            return new OrderedEnumerable(source, keySelector, null, false); 
        } 

        public static IOrderedEnumerable OrderBy(this IEnumerable source, Func keySelector, IComparer comparer) { 
            return new OrderedEnumerable(source, keySelector, comparer, false);
        }

        public static IOrderedEnumerable OrderByDescending(this IEnumerable source, Func keySelector) { 
            return new OrderedEnumerable(source, keySelector, null, true);
        } 
 
        public static IOrderedEnumerable OrderByDescending(this IEnumerable source, Func keySelector, IComparer comparer) {
            return new OrderedEnumerable(source, keySelector, comparer, true); 
        }

        public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, Func keySelector) {
            if (source == null) throw Error.ArgumentNull("source"); 
            return source.CreateOrderedEnumerable(keySelector, null, false);
        } 
 
        public static IOrderedEnumerable ThenBy(this IOrderedEnumerable source, Func keySelector, IComparer comparer) {
            if (source == null) throw Error.ArgumentNull("source"); 
            return source.CreateOrderedEnumerable(keySelector, comparer, false);
        }

        public static IOrderedEnumerable ThenByDescending(this IOrderedEnumerable source, Func keySelector) { 
            if (source == null) throw Error.ArgumentNull("source");
            return source.CreateOrderedEnumerable(keySelector, null, true); 
        } 

        public static IOrderedEnumerable ThenByDescending(this IOrderedEnumerable source, Func keySelector, IComparer comparer) { 
            if (source == null) throw Error.ArgumentNull("source");
            return source.CreateOrderedEnumerable(keySelector, comparer, true);
        }
 
        public static IEnumerable> GroupBy(this IEnumerable source, Func keySelector) {
            return new GroupedEnumerable(source, keySelector, IdentityFunction.Instance, null); 
        } 

        public static IEnumerable> GroupBy(this IEnumerable source, Func keySelector, IEqualityComparer comparer) { 
            return new GroupedEnumerable(source, keySelector, IdentityFunction.Instance, comparer);
        }

        public static IEnumerable> GroupBy(this IEnumerable source, Func keySelector, Func elementSelector) { 
            return new GroupedEnumerable(source, keySelector, elementSelector, null);
        } 
 
        public static IEnumerable> GroupBy(this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) {
            return new GroupedEnumerable(source, keySelector, elementSelector, comparer); 
        }

       public static IEnumerable GroupBy(this IEnumerable source, Func keySelector, Func, TResult> resultSelector){
           return  new GroupedEnumerable(source, keySelector, IdentityFunction.Instance, resultSelector, null); 
        }
 
        public static IEnumerable GroupBy(this IEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector){ 
           return new GroupedEnumerable(source, keySelector, elementSelector, resultSelector, null);
        } 

        public static IEnumerable GroupBy(this IEnumerable source, Func keySelector, Func, TResult> resultSelector, IEqualityComparer comparer){
            return  new GroupedEnumerable(source, keySelector, IdentityFunction.Instance, resultSelector, comparer);
        } 

        public static IEnumerable GroupBy(this IEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector, IEqualityComparer comparer){ 
            return  new GroupedEnumerable(source, keySelector, elementSelector, resultSelector, comparer); 
        }
 
        public static IEnumerable Concat(this IEnumerable first, IEnumerable second) {
            if (first == null) throw Error.ArgumentNull("first");
            if (second == null) throw Error.ArgumentNull("second");
            return ConcatIterator(first, second); 
        }
 
        static IEnumerable ConcatIterator(IEnumerable first, IEnumerable second) { 
            foreach (TSource element in first) yield return element;
            foreach (TSource element in second) yield return element; 
        }

        public static IEnumerable Zip(this IEnumerable first, IEnumerable second, Func resultSelector) {
            if (first == null) throw Error.ArgumentNull("first"); 
            if (second == null) throw Error.ArgumentNull("second");
            if (resultSelector == null) throw Error.ArgumentNull("resultSelector"); 
            return ZipIterator(first, second, resultSelector); 
        }
 
        static IEnumerable ZipIterator(IEnumerable first, IEnumerable second, Func resultSelector) {
            using (IEnumerator e1 = first.GetEnumerator())
                using (IEnumerator e2 = second.GetEnumerator())
                    while (e1.MoveNext() && e2.MoveNext()) 
                        yield return resultSelector(e1.Current, e2.Current);
        } 
 

        public static IEnumerable Distinct(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            return DistinctIterator(source, null);
        }
 
        public static IEnumerable Distinct(this IEnumerable source, IEqualityComparer comparer) {
            if (source == null) throw Error.ArgumentNull("source"); 
            return DistinctIterator(source, comparer); 
        }
 
        static IEnumerable DistinctIterator(IEnumerable source, IEqualityComparer comparer) {
            Set set = new Set(comparer);
            foreach (TSource element in source)
                if (set.Add(element)) yield return element; 
        }
 
        public static IEnumerable Union(this IEnumerable first, IEnumerable second) { 
            if (first == null) throw Error.ArgumentNull("first");
            if (second == null) throw Error.ArgumentNull("second"); 
            return UnionIterator(first, second, null);
        }

        public static IEnumerable Union(this IEnumerable first, IEnumerable second, IEqualityComparer comparer) 
        {
            if (first == null) throw Error.ArgumentNull("first"); 
            if (second == null) throw Error.ArgumentNull("second"); 
            return UnionIterator(first, second, comparer);
        } 

        static IEnumerable UnionIterator(IEnumerable first, IEnumerable second, IEqualityComparer comparer)
        {
            Set set = new Set(comparer); 
            foreach (TSource element in first)
                if (set.Add(element)) yield return element; 
            foreach (TSource element in second) 
                if (set.Add(element)) yield return element;
        } 

        public static IEnumerable Intersect(this IEnumerable first, IEnumerable second) {
            if (first == null) throw Error.ArgumentNull("first");
            if (second == null) throw Error.ArgumentNull("second"); 
            return IntersectIterator(first, second, null);
        } 
 
        public static IEnumerable Intersect(this IEnumerable first, IEnumerable second, IEqualityComparer comparer)
        { 
            if (first == null) throw Error.ArgumentNull("first");
            if (second == null) throw Error.ArgumentNull("second");
            return IntersectIterator(first, second, comparer);
        } 

        static IEnumerable IntersectIterator(IEnumerable first, IEnumerable second, IEqualityComparer comparer) 
        { 
            Set set = new Set(comparer);
            foreach (TSource element in second) set.Add(element); 
            foreach (TSource element in first)
                if (set.Remove(element)) yield return element;
        }
 
        public static IEnumerable Except(this IEnumerable first, IEnumerable second)
        { 
            if (first == null) throw Error.ArgumentNull("first"); 
            if (second == null) throw Error.ArgumentNull("second");
            return ExceptIterator(first, second, null); 
        }

        public static IEnumerable Except(this IEnumerable first, IEnumerable second, IEqualityComparer comparer)
        { 
            if (first == null) throw Error.ArgumentNull("first");
            if (second == null) throw Error.ArgumentNull("second"); 
            return ExceptIterator(first, second, comparer); 
        }
 
        static IEnumerable ExceptIterator(IEnumerable first, IEnumerable second, IEqualityComparer comparer) {
            Set set = new Set(comparer);
            foreach (TSource element in second) set.Add(element);
            foreach (TSource element in first) 
                if (set.Add(element)) yield return element;
        } 
 
        public static IEnumerable Reverse(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            return ReverseIterator(source);
        }

        static IEnumerable ReverseIterator(IEnumerable source) { 
            Buffer buffer = new Buffer(source);
            for (int i = buffer.count - 1; i >= 0; i--) yield return buffer.items[i]; 
        } 

        public static bool SequenceEqual(this IEnumerable first, IEnumerable second) { 
            return SequenceEqual(first, second, null);
        }

        public static bool SequenceEqual(this IEnumerable first, IEnumerable second, IEqualityComparer comparer) 
        {
            if (comparer == null) comparer = EqualityComparer.Default; 
            if (first == null) throw Error.ArgumentNull("first"); 
            if (second == null) throw Error.ArgumentNull("second");
            using (IEnumerator e1 = first.GetEnumerator()) 
            using (IEnumerator e2 = second.GetEnumerator())
            {
                while (e1.MoveNext())
                { 
                    if (!(e2.MoveNext() && comparer.Equals(e1.Current, e2.Current))) return false;
                } 
                if (e2.MoveNext()) return false; 
            }
            return true; 
        }

        public static IEnumerable AsEnumerable(this IEnumerable source)
        { 
            return source;
        } 
 
        public static TSource[] ToArray(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            return new Buffer(source).ToArray();
        }

        public static List ToList(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            return new List(source); 
        } 

        public static Dictionary ToDictionary(this IEnumerable source, Func keySelector) { 
            return ToDictionary(source, keySelector, IdentityFunction.Instance, null);
        }

        public static Dictionary ToDictionary(this IEnumerable source, Func keySelector, IEqualityComparer comparer) { 
            return ToDictionary(source, keySelector, IdentityFunction.Instance, comparer);
        } 
 
        public static Dictionary ToDictionary(this IEnumerable source, Func keySelector, Func elementSelector) {
            return ToDictionary(source, keySelector, elementSelector, null); 
        }

        public static Dictionary ToDictionary(this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (keySelector == null) throw Error.ArgumentNull("keySelector");
            if (elementSelector == null) throw Error.ArgumentNull("elementSelector"); 
            Dictionary d = new Dictionary(comparer); 
            foreach (TSource element in source) d.Add(keySelector(element), elementSelector(element));
            return d; 
        }

        public static ILookup ToLookup(this IEnumerable source, Func keySelector) {
            return Lookup.Create(source, keySelector, IdentityFunction.Instance, null); 
        }
 
        public static ILookup ToLookup(this IEnumerable source, Func keySelector, IEqualityComparer comparer) { 
            return Lookup.Create(source, keySelector, IdentityFunction.Instance, comparer);
        } 

        public static ILookup ToLookup(this IEnumerable source, Func keySelector, Func elementSelector) {
            return Lookup.Create(source, keySelector, elementSelector, null);
        } 

        public static ILookup ToLookup(this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) { 
            return Lookup.Create(source, keySelector, elementSelector, comparer); 
        }
 
        public static IEnumerable DefaultIfEmpty(this IEnumerable source) {
            return DefaultIfEmpty(source, default(TSource));
        }
 
        public static IEnumerable DefaultIfEmpty(this IEnumerable source, TSource defaultValue) {
            if (source == null) throw Error.ArgumentNull("source"); 
            return DefaultIfEmptyIterator(source, defaultValue); 
        }
 
        static IEnumerable DefaultIfEmptyIterator(IEnumerable source, TSource defaultValue) {
            using (IEnumerator e = source.GetEnumerator()) {
                if (e.MoveNext()) {
                    do { 
                        yield return e.Current;
                    } while (e.MoveNext()); 
                } 
                else {
                    yield return defaultValue; 
                }
            }
        }
 
        public static IEnumerable OfType(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            return OfTypeIterator(source); 
        }
 
        static IEnumerable OfTypeIterator(IEnumerable source) {
            foreach (object obj in source) {
                if (obj is TResult) yield return (TResult)obj;
            } 
        }
 
        public static IEnumerable Cast(this IEnumerable source) { 
            IEnumerable typedSource = source as IEnumerable;
            if (typedSource != null) return typedSource; 
            if (source == null) throw Error.ArgumentNull("source");
            return CastIterator(source);
        }
 
        static IEnumerable CastIterator(IEnumerable source) {
            foreach (object obj in source) yield return (TResult)obj; 
        } 

        public static TSource First(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            IList list = source as IList;
            if (list != null) {
                if (list.Count > 0) return list[0]; 
            }
            else { 
                using (IEnumerator e = source.GetEnumerator()) { 
                    if (e.MoveNext()) return e.Current;
                } 
            }
            throw Error.NoElements();
        }
 
        public static TSource First(this IEnumerable source, Func predicate) {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (predicate == null) throw Error.ArgumentNull("predicate"); 
            foreach (TSource element in source) {
                if (predicate(element)) return element; 
            }
            throw Error.NoMatch();
        }
 
        public static TSource FirstOrDefault(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            IList list = source as IList; 
            if (list != null) {
                if (list.Count > 0) return list[0]; 
            }
            else {
                using (IEnumerator e = source.GetEnumerator()) {
                    if (e.MoveNext()) return e.Current; 
                }
            } 
            return default(TSource); 
        }
 
        public static TSource FirstOrDefault(this IEnumerable source, Func predicate) {
            if (source == null) throw Error.ArgumentNull("source");
            if (predicate == null) throw Error.ArgumentNull("predicate");
            foreach (TSource element in source) { 
                if (predicate(element)) return element;
            } 
            return default(TSource); 
        }
 
        public static TSource Last(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source");
            IList list = source as IList;
            if (list != null) { 
                int count = list.Count;
                if (count > 0) return list[count - 1]; 
            } 
            else {
                using (IEnumerator e = source.GetEnumerator()) { 
                    if (e.MoveNext()) {
                        TSource result;
                        do {
                            result = e.Current; 
                        } while (e.MoveNext());
                        return result; 
                    } 
                }
            } 
            throw Error.NoElements();
        }

        public static TSource Last(this IEnumerable source, Func predicate) { 
            if (source == null) throw Error.ArgumentNull("source");
            if (predicate == null) throw Error.ArgumentNull("predicate"); 
            TSource result = default(TSource); 
            bool found = false;
            foreach (TSource element in source) { 
                if (predicate(element)) {
                    result = element;
                    found = true;
                } 
            }
            if (found) return result; 
            throw Error.NoMatch(); 
        }
 
        public static TSource LastOrDefault(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source");
            IList list = source as IList;
            if (list != null) { 
                int count = list.Count;
                if (count > 0) return list[count - 1]; 
            } 
            else {
                using (IEnumerator e = source.GetEnumerator()) { 
                    if (e.MoveNext()) {
                        TSource result;
                        do {
                            result = e.Current; 
                        } while (e.MoveNext());
                        return result; 
                    } 
                }
            } 
            return default(TSource);
        }

        public static TSource LastOrDefault(this IEnumerable source, Func predicate) { 
            if (source == null) throw Error.ArgumentNull("source");
            if (predicate == null) throw Error.ArgumentNull("predicate"); 
            TSource result = default(TSource); 
            foreach (TSource element in source) {
                if (predicate(element)) { 
                    result = element;
                }
            }
            return result; 
        }
 
        public static TSource Single(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            IList list = source as IList; 
            if (list != null) {
                switch (list.Count) {
                    case 0: throw Error.NoElements();
                    case 1: return list[0]; 
                }
            } 
            else { 
                using (IEnumerator e = source.GetEnumerator()) {
                    if (!e.MoveNext()) throw Error.NoElements(); 
                    TSource result = e.Current;
                    if (!e.MoveNext()) return result;
                }
            } 
            throw Error.MoreThanOneElement();
        } 
 
        public static TSource Single(this IEnumerable source, Func predicate) {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (predicate == null) throw Error.ArgumentNull("predicate");
            TSource result = default(TSource);
            long count = 0;
            foreach (TSource element in source) { 
                if (predicate(element)) {
                    result = element; 
                    checked { count++; } 
                }
            } 
            switch (count) {
                case 0: throw Error.NoMatch();
                case 1: return result;
            } 
            throw Error.MoreThanOneMatch();
        } 
 
        public static TSource SingleOrDefault(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            IList list = source as IList;
            if (list != null) {
                switch (list.Count) {
                    case 0: return default(TSource); 
                    case 1: return list[0];
                } 
            } 
            else {
                using (IEnumerator e = source.GetEnumerator()) { 
                    if (!e.MoveNext()) return default(TSource);
                    TSource result = e.Current;
                    if (!e.MoveNext()) return result;
                } 
            }
            throw Error.MoreThanOneElement(); 
        } 

        public static TSource SingleOrDefault(this IEnumerable source, Func predicate) { 
            if (source == null) throw Error.ArgumentNull("source");
            if (predicate == null) throw Error.ArgumentNull("predicate");
            TSource result = default(TSource);
            long count = 0; 
            foreach (TSource element in source) {
                if (predicate(element)) { 
                    result = element; 
                    checked { count++; }
                } 
            }
            switch (count) {
                case 0: return default(TSource);
                case 1: return result; 
            }
            throw Error.MoreThanOneMatch(); 
        } 

        public static TSource ElementAt(this IEnumerable source, int index) { 
            if (source == null) throw Error.ArgumentNull("source");
            IList list = source as IList;
            if (list != null) return list[index];
            if (index < 0) throw Error.ArgumentOutOfRange("index"); 
            using (IEnumerator e = source.GetEnumerator()) {
                while (true) { 
                    if (!e.MoveNext()) throw Error.ArgumentOutOfRange("index"); 
                    if (index == 0) return e.Current;
                    index--; 
                }
            }
        }
 
        public static TSource ElementAtOrDefault(this IEnumerable source, int index) {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (index >= 0) { 
                IList list = source as IList;
                if (list != null) { 
                    if (index < list.Count) return list[index];
                }
                else {
                    using (IEnumerator e = source.GetEnumerator()) { 
                        while (true) {
                            if (!e.MoveNext()) break; 
                            if (index == 0) return e.Current; 
                            index--;
                        } 
                    }
                }
            }
            return default(TSource); 
        }
 
        public static IEnumerable Range(int start, int count) { 
            long max = ((long)start) + count - 1;
            if (count < 0 || max > Int32.MaxValue) throw Error.ArgumentOutOfRange("count"); 
            return RangeIterator(start, count);
        }

        static IEnumerable RangeIterator(int start, int count) { 
            for (int i = 0; i < count; i++) yield return start + i;
        } 
 
        public static IEnumerable Repeat(TResult element, int count) {
            if (count < 0) throw Error.ArgumentOutOfRange("count"); 
            return RepeatIterator(element, count);
        }

        static IEnumerable RepeatIterator(TResult element, int count) { 
            for (int i = 0; i < count; i++) yield return element;
        } 
 
        public static IEnumerable Empty() {
            return EmptyEnumerable.Instance; 
        }

        public static bool Any(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            using (IEnumerator e = source.GetEnumerator()) {
                if (e.MoveNext()) return true; 
            } 
            return false;
        } 

        public static bool Any(this IEnumerable source, Func predicate) {
            if (source == null) throw Error.ArgumentNull("source");
            if (predicate == null) throw Error.ArgumentNull("predicate"); 
            foreach (TSource element in source) {
                if (predicate(element)) return true; 
            } 
            return false;
        } 

        public static bool All(this IEnumerable source, Func predicate) {
            if (source == null) throw Error.ArgumentNull("source");
            if (predicate == null) throw Error.ArgumentNull("predicate"); 
            foreach (TSource element in source) {
                if (!predicate(element)) return false; 
            } 
            return true;
        } 

        public static int Count(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source");
            ICollection collectionoft = source as ICollection; 
            if (collectionoft != null) return collectionoft.Count;
            ICollection collection = source as ICollection; 
            if (collection != null) return collection.Count; 
            int count = 0;
            using (IEnumerator e = source.GetEnumerator()) { 
                checked {
                    while (e.MoveNext()) count++;
                }
            } 
            return count;
        } 
 
        public static int Count(this IEnumerable source, Func predicate) {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (predicate == null) throw Error.ArgumentNull("predicate");
            int count = 0;
            foreach (TSource element in source) {
                checked { 
                    if (predicate(element)) count++;
                } 
            } 
            return count;
        } 

        public static long LongCount(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source");
            long count = 0; 
            using (IEnumerator e = source.GetEnumerator()) {
                checked { 
                    while (e.MoveNext()) count++; 
                }
            } 
            return count;
        }

        public static long LongCount(this IEnumerable source, Func predicate) { 
            if (source == null) throw Error.ArgumentNull("source");
            if (predicate == null) throw Error.ArgumentNull("predicate"); 
            long count = 0; 
            foreach (TSource element in source) {
                checked { 
                    if (predicate(element)) count++;
                }
            }
            return count; 
        }
 
        public static bool Contains(this IEnumerable source, TSource value) { 
            ICollection collection = source as ICollection;
            if (collection != null) return collection.Contains(value); 
            return Contains(source, value, null);
        }

        public static bool Contains(this IEnumerable source, TSource value, IEqualityComparer comparer) 
        {
            if (comparer == null) comparer = EqualityComparer.Default; 
            if (source == null) throw Error.ArgumentNull("source"); 
            foreach (TSource element in source)
                if (comparer.Equals(element, value)) return true; 
            return false;
        }

        public static TSource Aggregate(this IEnumerable source, Func func) 
        {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (func == null) throw Error.ArgumentNull("func"); 
            using (IEnumerator e = source.GetEnumerator()) {
                if (!e.MoveNext()) throw Error.NoElements(); 
                TSource result = e.Current;
                while (e.MoveNext()) result = func(result, e.Current);
                return result;
            } 
        }
 
        public static TAccumulate Aggregate(this IEnumerable source, TAccumulate seed, Func func) { 
            if (source == null) throw Error.ArgumentNull("source");
            if (func == null) throw Error.ArgumentNull("func"); 
            TAccumulate result = seed;
            foreach (TSource element in source) result = func(result, element);
            return result;
        } 

        public static TResult Aggregate(this IEnumerable source, TAccumulate seed, Func func, Func resultSelector) { 
            if (source == null) throw Error.ArgumentNull("source"); 
            if (func == null) throw Error.ArgumentNull("func");
            if (resultSelector == null) throw Error.ArgumentNull("resultSelector"); 
            TAccumulate result = seed;
            foreach (TSource element in source) result = func(result, element);
            return resultSelector(result);
        } 

        public static int Sum(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source"); 
            int sum = 0;
            checked { 
                foreach (int v in source) sum += v;
            }
            return sum;
        } 

        public static int? Sum(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source"); 
            int sum = 0;
            checked { 
                foreach (int? v in source) {
                    if (v != null) sum += v.GetValueOrDefault();
                }
            } 
            return sum;
        } 
 
        public static long Sum(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            long sum = 0;
            checked {
                foreach (long v in source) sum += v;
            } 
            return sum;
        } 
 
        public static long? Sum(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            long sum = 0;
            checked {
                foreach (long? v in source) {
                    if (v != null) sum += v.GetValueOrDefault(); 
                }
            } 
            return sum; 
        }
 
        public static float Sum(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source");
            double sum = 0;
            foreach (float v in source) sum += v; 
            return (float)sum;
        } 
 
        public static float? Sum(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            double sum = 0;
            foreach (float? v in source) {
                if (v != null) sum += v.GetValueOrDefault();
            } 
            return (float)sum;
        } 
 
        public static double Sum(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            double sum = 0;
            foreach (double v in source) sum += v;
            return sum;
        } 

        public static double? Sum(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source"); 
            double sum = 0;
            foreach (double? v in source) { 
                if (v != null) sum += v.GetValueOrDefault();
            }
            return sum;
        } 

        public static decimal Sum(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source"); 
            decimal sum = 0;
            foreach (decimal v in source) sum += v; 
            return sum;
        }

        public static decimal? Sum(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            decimal sum = 0; 
            foreach (decimal? v in source) { 
                if (v != null) sum += v.GetValueOrDefault();
            } 
            return sum;
        }

        public static int Sum(this IEnumerable source, Func selector) { 
            return Enumerable.Sum(Enumerable.Select(source, selector));
        } 
 
        public static int? Sum(this IEnumerable source, Func selector) {
            return Enumerable.Sum(Enumerable.Select(source, selector)); 
        }

        public static long Sum(this IEnumerable source, Func selector) {
            return Enumerable.Sum(Enumerable.Select(source, selector)); 
        }
 
        public static long? Sum(this IEnumerable source, Func selector) { 
            return Enumerable.Sum(Enumerable.Select(source, selector));
        } 

        public static float Sum(this IEnumerable source, Func selector) {
            return Enumerable.Sum(Enumerable.Select(source, selector));
        } 

        public static float? Sum(this IEnumerable source, Func selector) { 
            return Enumerable.Sum(Enumerable.Select(source, selector)); 
        }
 
        public static double Sum(this IEnumerable source, Func selector) {
            return Enumerable.Sum(Enumerable.Select(source, selector));
        }
 
        public static double? Sum(this IEnumerable source, Func selector) {
            return Enumerable.Sum(Enumerable.Select(source, selector)); 
        } 

        public static decimal Sum(this IEnumerable source, Func selector) { 
            return Enumerable.Sum(Enumerable.Select(source, selector));
        }

        public static decimal? Sum(this IEnumerable source, Func selector) { 
            return Enumerable.Sum(Enumerable.Select(source, selector));
        } 
 
        public static int Min(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            int value = 0;
            bool hasValue = false;
            foreach (int x in source) {
                if (hasValue) { 
                    if (x < value) value = x;
                } 
                else { 
                    value = x;
                    hasValue = true; 
                }
            }
            if (hasValue) return value;
            throw Error.NoElements(); 
        }
 
        public static int? Min(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            int? value = null; 
            foreach (int? x in source) {
                if (value == null || x < value)
                    value = x;
            } 
            return value;
        } 
 
        public static long Min(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            long value = 0;
            bool hasValue = false;
            foreach (long x in source) {
                if (hasValue) { 
                    if (x < value) value = x;
                } 
                else { 
                    value = x;
                    hasValue = true; 
                }
            }
            if (hasValue) return value;
            throw Error.NoElements(); 
        }
 
        public static long? Min(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            long? value = null; 
            foreach (long? x in source) {
                if (value == null || x < value) value = x;
            }
            return value; 
        }
 
        public static float Min(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            float value = 0; 
            bool hasValue = false;
            foreach (float x in source) {
                if (hasValue) {
                    // Normally NaN < anything is false, as is anything < NaN 
                    // However, this leads to some irksome outcomes in Min and Max.
                    // If we use those semantics then Min(NaN, 5.0) is NaN, but 
                    // Min(5.0, NaN) is 5.0!  To fix this, we impose a total 
                    // ordering where NaN is smaller than every value, including
                    // negative infinity. 
                    if (x < value || System.Single.IsNaN(x)) value = x;
                }
                else {
                    value = x; 
                    hasValue = true;
                } 
            } 
            if (hasValue) return value;
            throw Error.NoElements(); 
        }

        public static float? Min(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            float? value = null;
            foreach (float? x in source) { 
                if (x == null) continue; 
                if (value == null || x < value || System.Single.IsNaN((float)x)) value = x;
            } 
            return value;
        }

        public static double Min(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            double value = 0; 
            bool hasValue = false; 
            foreach (double x in source) {
                if (hasValue) { 
                    if (x < value || System.Double.IsNaN(x)) value = x;
                }
                else {
                    value = x; 
                    hasValue = true;
                } 
            } 
            if (hasValue) return value;
            throw Error.NoElements(); 
        }

        public static double? Min(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            double? value = null;
            foreach (double? x in source) { 
                if (x == null) continue; 
                if (value == null || x < value || System.Double.IsNaN((double)x)) value = x;
            } 
            return value;
        }

        public static decimal Min(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            decimal value = 0; 
            bool hasValue = false; 
            foreach (decimal x in source) {
                if (hasValue) { 
                    if (x < value) value = x;
                }
                else {
                    value = x; 
                    hasValue = true;
                } 
            } 
            if (hasValue) return value;
            throw Error.NoElements(); 
        }

        public static decimal? Min(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            decimal? value = null;
            foreach (decimal? x in source) { 
                if (value == null || x < value) value = x; 
            }
            return value; 
        }

        public static TSource Min(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            Comparer comparer = Comparer.Default;
            TSource value = default(TSource); 
            if (value == null) { 
                foreach (TSource x in source) {
                    if (x != null && (value == null || comparer.Compare(x, value) < 0)) 
                        value = x;
                }
                return value;
            } 
            else {
                bool hasValue = false; 
                foreach (TSource x in source) { 
                    if (hasValue) {
                        if (comparer.Compare(x, value) < 0) 
                            value = x;
                    }
                    else {
                        value = x; 
                        hasValue = true;
                    } 
                } 
                if (hasValue) return value;
                throw Error.NoElements(); 
            }
        }

        public static int Min(this IEnumerable source, Func selector) { 
            return Enumerable.Min(Enumerable.Select(source, selector));
        } 
 
        public static int? Min(this IEnumerable source, Func selector) {
            return Enumerable.Min(Enumerable.Select(source, selector)); 
        }

        public static long Min(this IEnumerable source, Func selector) {
            return Enumerable.Min(Enumerable.Select(source, selector)); 
        }
 
        public static long? Min(this IEnumerable source, Func selector) { 
            return Enumerable.Min(Enumerable.Select(source, selector));
        } 

        public static float Min(this IEnumerable source, Func selector) {
            return Enumerable.Min(Enumerable.Select(source, selector));
        } 

        public static float? Min(this IEnumerable source, Func selector) { 
            return Enumerable.Min(Enumerable.Select(source, selector)); 
        }
 
        public static double Min(this IEnumerable source, Func selector) {
            return Enumerable.Min(Enumerable.Select(source, selector));
        }
 
        public static double? Min(this IEnumerable source, Func selector) {
            return Enumerable.Min(Enumerable.Select(source, selector)); 
        } 

        public static decimal Min(this IEnumerable source, Func selector) { 
            return Enumerable.Min(Enumerable.Select(source, selector));
        }

        public static decimal? Min(this IEnumerable source, Func selector) { 
            return Enumerable.Min(Enumerable.Select(source, selector));
        } 
 
        public static TResult Min(this IEnumerable source, Func selector) {
            return Enumerable.Min(Enumerable.Select(source, selector)); 
        }

        public static int Max(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            int value = 0;
            bool hasValue = false; 
            foreach (int x in source) { 
                if (hasValue) {
                    if (x > value) value = x; 
                }
                else {
                    value = x;
                    hasValue = true; 
                }
            } 
            if (hasValue) return value; 
            throw Error.NoElements();
        } 

        public static int? Max(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source");
            int? value = null; 
            foreach (int? x in source) {
                if (value == null || x > value) value = x; 
            } 
            return value;
        } 

        public static long Max(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source");
            long value = 0; 
            bool hasValue = false;
            foreach (long x in source) { 
                if (hasValue) { 
                    if (x > value) value = x;
                } 
                else {
                    value = x;
                    hasValue = true;
                } 
            }
            if (hasValue) return value; 
            throw Error.NoElements(); 
        }
 
        public static long? Max(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source");
            long? value = null;
            foreach (long? x in source) { 
                if (value == null || x > value) value = x;
            } 
            return value; 
        }
 
        public static double Max(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source");
            double value = 0;
            bool hasValue = false; 
            foreach (double x in source) {
                if (hasValue) { 
                    if (x > value || System.Double.IsNaN(value)) value = x; 
                }
                else { 
                    value = x;
                    hasValue = true;
                }
            } 
            if (hasValue) return value;
            throw Error.NoElements(); 
        } 

        public static double? Max(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            double? value = null;
            foreach (double? x in source) {
                if (x == null) continue; 
                if (value == null || x > value || System.Double.IsNaN((double)value)) value = x;
            } 
            return value; 
        }
 
        public static float Max(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source");
            float value = 0;
            bool hasValue = false; 
            foreach (float x in source) {
                if (hasValue) { 
                    if (x > value || System.Double.IsNaN(value)) value = x; 
                }
                else { 
                    value = x;
                    hasValue = true;
                }
            } 
            if (hasValue) return value;
            throw Error.NoElements(); 
        } 

        public static float? Max(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            float? value = null;
            foreach (float? x in source) {
                if (x == null) continue; 
                if (value == null || x > value || System.Single.IsNaN((float)value)) value = x;
            } 
            return value; 
        }
 
        public static decimal Max(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source");
            decimal value = 0;
            bool hasValue = false; 
            foreach (decimal x in source) {
                if (hasValue) { 
                    if (x > value) value = x; 
                }
                else { 
                    value = x;
                    hasValue = true;
                }
            } 
            if (hasValue) return value;
            throw Error.NoElements(); 
        } 

        public static decimal? Max(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            decimal? value = null;
            foreach (decimal? x in source) {
                if (value == null || x > value) value = x; 
            }
            return value; 
        } 

        public static TSource Max(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            Comparer comparer = Comparer.Default;
            TSource value = default(TSource);
            if (value == null) { 
                foreach (TSource x in source) {
                    if (x != null && (value == null || comparer.Compare(x, value) > 0)) 
                        value = x; 
                }
                return value; 
            }
            else {
                bool hasValue = false;
                foreach (TSource x in source) { 
                    if (hasValue) {
                        if (comparer.Compare(x, value) > 0) 
                            value = x; 
                    }
                    else { 
                        value = x;
                        hasValue = true;
                    }
                } 
                if (hasValue) return value;
                throw Error.NoElements(); 
            } 
        }
 
        public static int Max(this IEnumerable source, Func selector) {
            return Enumerable.Max(Enumerable.Select(source, selector));
        }
 
        public static int? Max(this IEnumerable source, Func selector) {
            return Enumerable.Max(Enumerable.Select(source, selector)); 
        } 

        public static long Max(this IEnumerable source, Func selector) { 
            return Enumerable.Max(Enumerable.Select(source, selector));
        }

        public static long? Max(this IEnumerable source, Func selector) { 
            return Enumerable.Max(Enumerable.Select(source, selector));
        } 
 
        public static float Max(this IEnumerable source, Func selector) {
            return Enumerable.Max(Enumerable.Select(source, selector)); 
        }

        public static float? Max(this IEnumerable source, Func selector) {
            return Enumerable.Max(Enumerable.Select(source, selector)); 
        }
 
        public static double Max(this IEnumerable source, Func selector) { 
            return Enumerable.Max(Enumerable.Select(source, selector));
        } 

        public static double? Max(this IEnumerable source, Func selector) {
            return Enumerable.Max(Enumerable.Select(source, selector));
        } 

        public static decimal Max(this IEnumerable source, Func selector) { 
            return Enumerable.Max(Enumerable.Select(source, selector)); 
        }
 
        public static decimal? Max(this IEnumerable source, Func selector) {
            return Enumerable.Max(Enumerable.Select(source, selector));
        }
 
        public static TResult Max(this IEnumerable source, Func selector) {
            return Enumerable.Max(Enumerable.Select(source, selector)); 
        } 

        public static double Average(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            long sum = 0;
            long count = 0;
            checked { 
                foreach (int v in source) {
                    sum += v; 
                    count++; 
                }
            } 
            if (count > 0) return (double)sum / count;
            throw Error.NoElements();
        }
 
        public static double? Average(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            long sum = 0; 
            long count = 0;
            checked { 
                foreach (int? v in source) {
                    if (v != null) {
                        sum += v.GetValueOrDefault();
                        count++; 
                    }
                } 
            } 
            if (count > 0) return (double)sum / count;
            return null; 
        }

        public static double Average(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            long sum = 0;
            long count = 0; 
            checked { 
                foreach (long v in source) {
                    sum += v; 
                    count++;
                }
            }
            if (count > 0) return (double)sum / count; 
            throw Error.NoElements();
        } 
 
        public static double? Average(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            long sum = 0;
            long count = 0;
            checked {
                foreach (long? v in source) { 
                    if (v != null) {
                        sum += v.GetValueOrDefault(); 
                        count++; 
                    }
                } 
            }
            if (count > 0) return (double)sum / count;
            return null;
        } 

        public static float Average(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source"); 
            double sum = 0;
            long count = 0; 
            checked {
                foreach (float v in source) {
                    sum += v;
                    count++; 
                }
            } 
            if (count > 0) return (float)(sum / count); 
            throw Error.NoElements();
        } 

        public static float? Average(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source");
            double sum = 0; 
            long count = 0;
            checked { 
                foreach (float? v in source) { 
                    if (v != null) {
                        sum += v.GetValueOrDefault(); 
                        count++;
                    }
                }
            } 
            if (count > 0) return (float)(sum / count);
            return null; 
        } 

        public static double Average(this IEnumerable source) { 
            if (source == null) throw Error.ArgumentNull("source");
            double sum = 0;
            long count = 0;
            checked { 
                foreach (double v in source) {
                    sum += v; 
                    count++; 
                }
            } 
            if (count > 0) return sum / count;
            throw Error.NoElements();
        }
 
        public static double? Average(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            double sum = 0; 
            long count = 0;
            checked { 
                foreach (double? v in source) {
                    if (v != null) {
                        sum += v.GetValueOrDefault();
                        count++; 
                    }
                } 
            } 
            if (count > 0) return sum / count;
            return null; 
        }

        public static decimal Average(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            decimal sum = 0;
            long count = 0; 
            checked { 
                foreach (decimal v in source) {
                    sum += v; 
                    count++;
                }
            }
            if (count > 0) return sum / count; 
            throw Error.NoElements();
        } 
 
        public static decimal? Average(this IEnumerable source) {
            if (source == null) throw Error.ArgumentNull("source"); 
            decimal sum = 0;
            long count = 0;
            checked {
                foreach (decimal? v in source) { 
                    if (v != null) {
                        sum += v.GetValueOrDefault(); 
                        count++; 
                    }
                } 
            }
            if (count > 0) return sum / count;
            return null;
        } 

        public static double Average(this IEnumerable source, Func selector) { 
            return Enumerable.Average(Enumerable.Select(source, selector)); 
        }
 
        public static double? Average(this IEnumerable source, Func selector) {
            return Enumerable.Average(Enumerable.Select(source, selector));
        }
 
        public static double Average(this IEnumerable source, Func selector) {
            return Enumerable.Average(Enumerable.Select(source, selector)); 
        } 

        public static double? Average(this IEnumerable source, Func selector) { 
            return Enumerable.Average(Enumerable.Select(source, selector));
        }

        public static float Average(this IEnumerable source, Func selector) { 
            return Enumerable.Average(Enumerable.Select(source, selector));
        } 
 
        public static float? Average(this IEnumerable source, Func selector) {
            return Enumerable.Average(Enumerable.Select(source, selector)); 
        }

        public static double Average(this IEnumerable source, Func selector) {
            return Enumerable.Average(Enumerable.Select(source, selector)); 
        }
 
        public static double? Average(this IEnumerable source, Func selector) { 
            return Enumerable.Average(Enumerable.Select(source, selector));
        } 

        public static decimal Average(this IEnumerable source, Func selector) {
            return Enumerable.Average(Enumerable.Select(source, selector));
        } 

        public static decimal? Average(this IEnumerable source, Func selector) { 
            return Enumerable.Average(Enumerable.Select(source, selector)); 
        }
    } 

    internal class EmptyEnumerable
    {
        static TElement[] instance; 

        public static IEnumerable Instance { 
            get { 
                if (instance == null) instance = new TElement[0];
                return instance; 
            }
        }
    }
 
    internal class IdentityFunction
    { 
        public static Func Instance { 
            get { return x => x; }
        } 
    }

    public interface IOrderedEnumerable : IEnumerable
    { 
        IOrderedEnumerable CreateOrderedEnumerable(Func keySelector, IComparer comparer, bool descending);
    } 
 
#if SILVERLIGHT
    public interface IGrouping : IEnumerable 
#else
    public interface IGrouping : IEnumerable
#endif
    { 
        TKey Key { get; }
    } 
 
    public interface ILookup : IEnumerable>{
        int Count { get; } 
        IEnumerable this[TKey key] { get; }
        bool Contains(TKey key);
    }
 
    public class Lookup : IEnumerable>, ILookup{
        IEqualityComparer comparer; 
        Grouping[] groupings; 
        Grouping lastGrouping;
        int count; 

        internal static Lookup Create(IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) {
            if (source == null) throw Error.ArgumentNull("source");
            if (keySelector == null) throw Error.ArgumentNull("keySelector"); 
            if (elementSelector == null) throw Error.ArgumentNull("elementSelector");
            Lookup lookup = new Lookup(comparer); 
            foreach (TSource item in source) { 
                lookup.GetGrouping(keySelector(item), true).Add(elementSelector(item));
            } 
            return lookup;
        }

        internal static Lookup CreateForJoin(IEnumerable source, Func keySelector, IEqualityComparer comparer) { 
            Lookup lookup = new Lookup(comparer);
            foreach (TElement item in source) { 
                TKey key = keySelector(item); 
                if (key != null) lookup.GetGrouping(key, true).Add(item);
            } 
            return lookup;
        }

        Lookup(IEqualityComparer comparer) { 
            if (comparer == null) comparer = EqualityComparer.Default;
            this.comparer = comparer; 
            groupings = new Grouping[7]; 
        }
 
        public int Count {
            get { return count; }
        }
 
        public IEnumerable this[TKey key] {
            get { 
                Grouping grouping = GetGrouping(key, false); 
                if (grouping != null) return grouping;
                return EmptyEnumerable.Instance; 
            }
        }

        public bool Contains(TKey key) { 
            return GetGrouping(key, false) != null;
        } 
 
        public IEnumerator> GetEnumerator() {
            Grouping g = lastGrouping; 
            if (g != null) {
                do {
                    g = g.next;
                    yield return g; 
                } while (g != lastGrouping);
            } 
        } 

        public IEnumerable ApplyResultSelector(Func, TResult> resultSelector){ 
            Grouping g = lastGrouping;
            if (g != null) {
                do {
                    g = g.next; 
                    if (g.count != g.elements.Length) { Array.Resize(ref g.elements, g.count); }
                    yield return resultSelector(g.key, g.elements); 
                }while (g != lastGrouping); 
            }
        } 

        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator();
        } 

        internal int InternalGetHashCode(TKey key) 
        { 
            //[....] DevDivBugs 171937. work around comparer implementations that throw when passed null
            return (key == null) ? 0 : comparer.GetHashCode(key) & 0x7FFFFFFF; 
        }

        internal Grouping GetGrouping(TKey key, bool create) {
            int hashCode = InternalGetHashCode(key); 
            for (Grouping g = groupings[hashCode % groupings.Length]; g != null; g = g.hashNext)
                if (g.hashCode == hashCode && comparer.Equals(g.key, key)) return g; 
            if (create) { 
                if (count == groupings.Length) Resize();
                int index = hashCode % groupings.Length; 
                Grouping g = new Grouping();
                g.key = key;
                g.hashCode = hashCode;
                g.elements = new TElement[1]; 
                g.hashNext = groupings[index];
                groupings[index] = g; 
                if (lastGrouping == null) { 
                    g.next = g;
                } 
                else {
                    g.next = lastGrouping.next;
                    lastGrouping.next = g;
                } 
                lastGrouping = g;
                count++; 
                return g; 
            }
            return null; 
        }

        void Resize() {
            int newSize = checked(count * 2 + 1); 
            Grouping[] newGroupings = new Grouping[newSize];
            Grouping g = lastGrouping; 
            do { 
                g = g.next;
                int index = g.hashCode % newSize; 
                g.hashNext = newGroupings[index];
                newGroupings[index] = g;
            } while (g != lastGrouping);
            groupings = newGroupings; 
        }
 
        internal class Grouping : IGrouping, IList 
        {
            internal TKey key; 
            internal int hashCode;
            internal TElement[] elements;
            internal int count;
            internal Grouping hashNext; 
            internal Grouping next;
 
            internal void Add(TElement element) { 
                if (elements.Length == count) Array.Resize(ref elements, checked(count * 2));
                elements[count] = element; 
                count++;
            }

            public IEnumerator GetEnumerator() { 
                for (int i = 0; i < count; i++) yield return elements[i];
            } 
 
            IEnumerator IEnumerable.GetEnumerator() {
                return GetEnumerator(); 
            }

            // DDB195907: implement IGrouping<>.Key implicitly
            // so that WPF binding works on this property. 
            public TKey Key {
                get { return key; } 
            } 

            int ICollection.Count { 
                get { return count; }
            }

            bool ICollection.IsReadOnly { 
                get { return true; }
            } 
 
            void ICollection.Add(TElement item) {
                throw Error.NotSupported(); 
            }

            void ICollection.Clear() {
                throw Error.NotSupported(); 
            }
 
            bool ICollection.Contains(TElement item) { 
                return Array.IndexOf(elements, item, 0, count) >= 0;
            } 

            void ICollection.CopyTo(TElement[] array, int arrayIndex) {
                Array.Copy(elements, 0, array, arrayIndex, count);
            } 

            bool ICollection.Remove(TElement item) { 
                throw Error.NotSupported(); 
            }
 
            int IList.IndexOf(TElement item) {
                return Array.IndexOf(elements, item, 0, count);
            }
 
            void IList.Insert(int index, TElement item) {
                throw Error.NotSupported(); 
            } 

            void IList.RemoveAt(int index) { 
                throw Error.NotSupported();
            }

            TElement IList.this[int index] { 
                get {
                    if (index < 0 || index >= count) throw Error.ArgumentOutOfRange("index"); 
                    return elements[index]; 
                }
                set { 
                    throw Error.NotSupported();
                }
            }
        } 
    }
 
    internal class Set 
    {
        int[] buckets; 
        Slot[] slots;
        int count;
        int freeList;
        IEqualityComparer comparer; 

        public Set() : this(null) { } 
 
        public Set(IEqualityComparer comparer) {
            if (comparer == null) comparer = EqualityComparer.Default; 
            this.comparer = comparer;
            buckets = new int[7];
            slots = new Slot[7];
            freeList = -1; 
        }
 
        // If value is not in set, add it and return true; otherwise return false 
        public bool Add(TElement value) {
            return !Find(value, true); 
        }

        // Check whether value is in set
        public bool Contains(TElement value) { 
            return Find(value, false);
        } 
 
        // If value is in set, remove it and return true; otherwise return false
        public bool Remove(TElement value) { 
            int hashCode = InternalGetHashCode(value);
            int bucket = hashCode % buckets.Length;
            int last = -1;
            for (int i = buckets[bucket] - 1; i >= 0; last = i, i = slots[i].next) { 
                if (slots[i].hashCode == hashCode && comparer.Equals(slots[i].value, value)) {
                    if (last < 0) { 
                        buckets[bucket] = slots[i].next + 1; 
                    }
                    else { 
                        slots[last].next = slots[i].next;
                    }
                    slots[i].hashCode = -1;
                    slots[i].value = default(TElement); 
                    slots[i].next = freeList;
                    freeList = i; 
                    return true; 
                }
            } 
            return false;
        }

        bool Find(TElement value, bool add) { 
            int hashCode = InternalGetHashCode(value);
            for (int i = buckets[hashCode % buckets.Length] - 1; i >= 0; i = slots[i].next) { 
                if (slots[i].hashCode == hashCode && comparer.Equals(slots[i].value, value)) return true; 
            }
            if (add) { 
                int index;
                if (freeList >= 0) {
                    index = freeList;
                    freeList = slots[index].next; 
                }
                else { 
                    if (count == slots.Length) Resize(); 
                    index = count;
                    count++; 
                }
                int bucket = hashCode % buckets.Length;
                slots[index].hashCode = hashCode;
                slots[index].value = value; 
                slots[index].next = buckets[bucket] - 1;
                buckets[bucket] = index + 1; 
            } 
            return false;
        } 

        void Resize() {
            int newSize = checked(count * 2 + 1);
            int[] newBuckets = new int[newSize]; 
            Slot[] newSlots = new Slot[newSize];
            Array.Copy(slots, 0, newSlots, 0, count); 
            for (int i = 0; i < count; i++) { 
                int bucket = newSlots[i].hashCode % newSize;
                newSlots[i].next = newBuckets[bucket] - 1; 
                newBuckets[bucket] = i + 1;
            }
            buckets = newBuckets;
            slots = newSlots; 
        }
 
        internal int InternalGetHashCode(TElement value) 
        {
            //[....] DevDivBugs 171937. work around comparer implementations that throw when passed null 
            return (value == null) ? 0 : comparer.GetHashCode(value) & 0x7FFFFFFF;
        }

        internal struct Slot 
        {
            internal int hashCode; 
            internal TElement value; 
            internal int next;
        } 
    }

    internal class GroupedEnumerable : IEnumerable{
        IEnumerable source; 
        Func keySelector;
        Func elementSelector; 
        IEqualityComparer comparer; 
        Func, TResult> resultSelector;
 
        public GroupedEnumerable(IEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector, IEqualityComparer comparer){
            if (source == null) throw Error.ArgumentNull("source");
            if (keySelector == null) throw Error.ArgumentNull("keySelector");
            if (elementSelector == null) throw Error.ArgumentNull("elementSelector"); 
            if (resultSelector == null) throw Error.ArgumentNull("resultSelector");
            this.source = source; 
            this.keySelector = keySelector; 
            this.elementSelector = elementSelector;
            this.comparer = comparer; 
            this.resultSelector = resultSelector;
        }

        public IEnumerator GetEnumerator(){ 
            Lookup lookup = Lookup.Create(source, keySelector, elementSelector, comparer);
            return lookup.ApplyResultSelector(resultSelector).GetEnumerator(); 
        } 

        IEnumerator IEnumerable.GetEnumerator(){ 
            return GetEnumerator();
        }
    }
 
    internal class GroupedEnumerable : IEnumerable>
    { 
        IEnumerable source; 
        Func keySelector;
        Func elementSelector; 
        IEqualityComparer comparer;

        public GroupedEnumerable(IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (keySelector == null) throw Error.ArgumentNull("keySelector");
            if (elementSelector == null) throw Error.ArgumentNull("elementSelector"); 
            this.source = source; 
            this.keySelector = keySelector;
            this.elementSelector = elementSelector; 
            this.comparer = comparer;
        }

        public IEnumerator> GetEnumerator() { 
            return Lookup.Create(source, keySelector, elementSelector, comparer).GetEnumerator();
        } 
 
        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator(); 
        }
    }

    internal abstract class OrderedEnumerable : IOrderedEnumerable 
    {
        internal IEnumerable source; 
 
        public IEnumerator GetEnumerator() {
            Buffer buffer = new Buffer(source); 
            if (buffer.count > 0) {
                EnumerableSorter sorter = GetEnumerableSorter(null);
                int[] map = sorter.Sort(buffer.items, buffer.count);
                sorter = null; 
                for (int i = 0; i < buffer.count; i++) yield return buffer.items[map[i]];
            } 
        } 

        internal abstract EnumerableSorter GetEnumerableSorter(EnumerableSorter next); 

        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator();
        } 

        IOrderedEnumerable IOrderedEnumerable.CreateOrderedEnumerable(Func keySelector, IComparer comparer, bool descending) { 
            OrderedEnumerable result = new OrderedEnumerable(source, keySelector, comparer, descending); 
            result.parent = this;
            return result; 
        }
    }

    internal class OrderedEnumerable : OrderedEnumerable 
    {
        internal OrderedEnumerable parent; 
        internal Func keySelector; 
        internal IComparer comparer;
        internal bool descending; 

        internal OrderedEnumerable(IEnumerable source, Func keySelector, IComparer comparer, bool descending) {
            if (source == null) throw Error.ArgumentNull("source");
            if (keySelector == null) throw Error.ArgumentNull("keySelector"); 
            this.source = source;
            this.parent = null; 
            this.keySelector = keySelector; 
            this.comparer = comparer != null ? comparer : Comparer.Default;
            this.descending = descending; 
        }

        internal override EnumerableSorter GetEnumerableSorter(EnumerableSorter next) {
            EnumerableSorter sorter = new EnumerableSorter(keySelector, comparer, descending, next); 
            if (parent != null) sorter = parent.GetEnumerableSorter(sorter);
            return sorter; 
        } 
    }
 
    internal abstract class EnumerableSorter
    {
        internal abstract void ComputeKeys(TElement[] elements, int count);
 
        internal abstract int CompareKeys(int index1, int index2);
 
        internal int[] Sort(TElement[] elements, int count) { 
            ComputeKeys(elements, count);
            int[] map = new int[count]; 
            for (int i = 0; i < count; i++) map[i] = i;
            QuickSort(map, 0, count - 1);
            return map;
        } 

        void QuickSort(int[] map, int left, int right) { 
            do { 
                int i = left;
                int j = right; 
                int x = map[i + ((j - i) >> 1)];
                do {
                    while (i < map.Length && CompareKeys(x, map[i]) > 0) i++;
                    while (j >= 0 && CompareKeys(x, map[j]) < 0) j--; 
                    if (i > j) break;
                    if (i < j) { 
                        int temp = map[i]; 
                        map[i] = map[j];
                        map[j] = temp; 
                    }
                    i++;
                    j--;
                } while (i <= j); 
                if (j - left <= right - i) {
                    if (left < j) QuickSort(map, left, j); 
                    left = i; 
                }
                else { 
                    if (i < right) QuickSort(map, i, right);
                    right = j;
                }
            } while (left < right); 
        }
    } 
 
    internal class EnumerableSorter : EnumerableSorter
    { 
        internal Func keySelector;
        internal IComparer comparer;
        internal bool descending;
        internal EnumerableSorter next; 
        internal TKey[] keys;
 
        internal EnumerableSorter(Func keySelector, IComparer comparer, bool descending, EnumerableSorter next) { 
            this.keySelector = keySelector;
            this.comparer = comparer; 
            this.descending = descending;
            this.next = next;
        }
 
        internal override void ComputeKeys(TElement[] elements, int count) {
            keys = new TKey[count]; 
            for (int i = 0; i < count; i++) keys[i] = keySelector(elements[i]); 
            if (next != null) next.ComputeKeys(elements, count);
        } 

        internal override int CompareKeys(int index1, int index2) {
            int c = comparer.Compare(keys[index1], keys[index2]);
            if (c == 0) { 
                if (next == null) return index1 - index2;
                return next.CompareKeys(index1, index2); 
            } 
            return descending ? -c : c;
        } 
    }

    struct Buffer
    { 
        internal TElement[] items;
        internal int count; 
 
        internal Buffer(IEnumerable source) {
            TElement[] items = null; 
            int count = 0;
            ICollection collection = source as ICollection;
            if (collection != null) {
                count = collection.Count; 
                if (count > 0) {
                    items = new TElement[count]; 
                    collection.CopyTo(items, 0); 
                }
            } 
            else {
                foreach (TElement item in source) {
                    if (items == null) {
                        items = new TElement[4]; 
                    }
                    else if (items.Length == count) { 
                        TElement[] newItems = new TElement[checked(count * 2)]; 
                        Array.Copy(items, 0, newItems, 0, count);
                        items = newItems; 
                    }
                    items[count] = item;
                    count++;
                } 
            }
            this.items = items; 
            this.count = count; 
        }
 
        internal TElement[] ToArray() {
            if (count == 0) return new TElement[0];
            if (items.Length == count) return items;
            TElement[] result = new TElement[count]; 
            Array.Copy(items, 0, result, 0, count);
            return result; 
        } 
    }
 
    /// 
    /// This class provides the items view for the Enumerable
    /// 
    ///  
    internal sealed class SystemCore_EnumerableDebugView
    { 
        public SystemCore_EnumerableDebugView(IEnumerable enumerable) 
        {
            if (enumerable == null) 
            {
                throw new ArgumentNullException("enumerable");
            }
 
            this.enumerable = enumerable;
        } 
 
        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
        public T[] Items 
        {
            get
            {
                List tempList = new List(); 
                IEnumerator currentEnumerator = this.enumerable.GetEnumerator();
 
                if (currentEnumerator != null) 
                {
                    for(count = 0; currentEnumerator.MoveNext(); count++) 
                    {
                        tempList.Add(currentEnumerator.Current);
                    }
                } 
                if (count == 0)
                { 
                    throw new SystemCore_EnumerableDebugViewEmptyException(); 
                }
                cachedCollection = new T[this.count]; 
                tempList.CopyTo(cachedCollection, 0);
                return cachedCollection;
            }
        } 

        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 
        private IEnumerable enumerable; 

        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 
        private T[] cachedCollection;

        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private int count; 
    }
 
    internal sealed class SystemCore_EnumerableDebugViewEmptyException : Exception 
    {
        public string Empty 
        {
            get
            {
                return Strings.EmptyEnumerable; 
            }
        } 
    } 

    internal sealed class SystemCore_EnumerableDebugView 
    {
        public SystemCore_EnumerableDebugView(IEnumerable enumerable)
        {
            if (enumerable == null) 
            {
                throw new ArgumentNullException("enumerable"); 
            } 

            this.enumerable = enumerable; 
            count = 0;
            cachedCollection = null;
        }
 
        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
        public object[] Items 
        { 
            get
            { 
                List tempList = new List();
                IEnumerator currentEnumerator = this.enumerable.GetEnumerator();

                if (currentEnumerator != null) 
                {
                    for (count = 0; currentEnumerator.MoveNext(); count++) 
                    { 
                        tempList.Add(currentEnumerator.Current);
                    } 
                }
                if (count == 0)
                {
                    throw new SystemCore_EnumerableDebugViewEmptyException(); 
                }
                cachedCollection = new object[this.count]; 
                tempList.CopyTo(cachedCollection, 0); 
                return cachedCollection;
            } 
        }

        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private IEnumerable enumerable; 

        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 
        private object[] cachedCollection; 

        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)] 
        private int count;
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK