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 volatile 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) { //EDMAURER 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(); } } } } // @BUG: Dev10 858919 (zlatkom). PLINQ is now using this class (Dev11 MQ). 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) { //EDMAURER 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; } }