Permalink
3b1eaf5 May 14, 2018
2 contributors

Users who have contributed to this file

@dotnet-bot @rbhanda
2818 lines (2449 sloc) 117 KB
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 partial class Enumerable
{
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
if (source is Iterator<TSource>) return ((Iterator<TSource>)source).Where(predicate);
if (source is TSource[]) return new WhereArrayIterator<TSource>((TSource[])source, predicate);
if (source is List<TSource>) return new WhereListIterator<TSource>((List<TSource>)source, predicate);
return new WhereEnumerableIterator<TSource>(source, predicate);
}
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
return WhereIterator<TSource>(source, predicate);
}
static IEnumerable<TSource> WhereIterator<TSource>(IEnumerable<TSource> source, Func<TSource, int, bool> predicate) {
int index = -1;
foreach (TSource element in source) {
checked { index++; }
if (predicate(element, index)) yield return element;
}
}
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) {
if (source == null) throw Error.ArgumentNull("source");
if (selector == null) throw Error.ArgumentNull("selector");
if (source is Iterator<TSource>) return ((Iterator<TSource>)source).Select(selector);
if (source is TSource[]) return new WhereSelectArrayIterator<TSource, TResult>((TSource[])source, null, selector);
if (source is List<TSource>) return new WhereSelectListIterator<TSource, TResult>((List<TSource>)source, null, selector);
return new WhereSelectEnumerableIterator<TSource, TResult>(source, null, selector);
}
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> selector) {
if (source == null) throw Error.ArgumentNull("source");
if (selector == null) throw Error.ArgumentNull("selector");
return SelectIterator<TSource, TResult>(source, selector);
}
static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, TResult> selector) {
int index = -1;
foreach (TSource element in source) {
checked { index++; }
yield return selector(element, index);
}
}
static Func<TSource, bool> CombinePredicates<TSource>(Func<TSource, bool> predicate1, Func<TSource, bool> predicate2) {
return x => predicate1(x) && predicate2(x);
}
static Func<TSource, TResult> CombineSelectors<TSource, TMiddle, TResult>(Func<TSource, TMiddle> selector1, Func<TMiddle, TResult> selector2) {
return x => selector2(selector1(x));
}
abstract class Iterator<TSource> : IEnumerable<TSource>, IEnumerator<TSource>
{
int threadId;
internal int state;
internal TSource current;
public Iterator() {
threadId = Thread.CurrentThread.ManagedThreadId;
}
public TSource Current {
get { return current; }
}
public abstract Iterator<TSource> Clone();
public virtual void Dispose() {
current = default(TSource);
state = -1;
}
public IEnumerator<TSource> GetEnumerator() {
if (threadId == Thread.CurrentThread.ManagedThreadId && state == 0) {
state = 1;
return this;
}
Iterator<TSource> duplicate = Clone();
duplicate.state = 1;
return duplicate;
}
public abstract bool MoveNext();
public abstract IEnumerable<TResult> Select<TResult>(Func<TSource, TResult> selector);
public abstract IEnumerable<TSource> Where(Func<TSource, bool> predicate);
object IEnumerator.Current {
get { return Current; }
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
void IEnumerator.Reset() {
throw new NotImplementedException();
}
}
class WhereEnumerableIterator<TSource> : Iterator<TSource>
{
IEnumerable<TSource> source;
Func<TSource, bool> predicate;
IEnumerator<TSource> enumerator;
public WhereEnumerableIterator(IEnumerable<TSource> source, Func<TSource, bool> predicate) {
this.source = source;
this.predicate = predicate;
}
public override Iterator<TSource> Clone() {
return new WhereEnumerableIterator<TSource>(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<TResult> Select<TResult>(Func<TSource, TResult> selector) {
return new WhereSelectEnumerableIterator<TSource, TResult>(source, predicate, selector);
}
public override IEnumerable<TSource> Where(Func<TSource, bool> predicate) {
return new WhereEnumerableIterator<TSource>(source, CombinePredicates(this.predicate, predicate));
}
}
class WhereArrayIterator<TSource> : Iterator<TSource>
{
TSource[] source;
Func<TSource, bool> predicate;
int index;
public WhereArrayIterator(TSource[] source, Func<TSource, bool> predicate) {
this.source = source;
this.predicate = predicate;
}
public override Iterator<TSource> Clone() {
return new WhereArrayIterator<TSource>(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<TResult> Select<TResult>(Func<TSource, TResult> selector) {
return new WhereSelectArrayIterator<TSource, TResult>(source, predicate, selector);
}
public override IEnumerable<TSource> Where(Func<TSource, bool> predicate) {
return new WhereArrayIterator<TSource>(source, CombinePredicates(this.predicate, predicate));
}
}
class WhereListIterator<TSource> : Iterator<TSource>
{
List<TSource> source;
Func<TSource, bool> predicate;
List<TSource>.Enumerator enumerator;
public WhereListIterator(List<TSource> source, Func<TSource, bool> predicate) {
this.source = source;
this.predicate = predicate;
}
public override Iterator<TSource> Clone() {
return new WhereListIterator<TSource>(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<TResult> Select<TResult>(Func<TSource, TResult> selector) {
return new WhereSelectListIterator<TSource, TResult>(source, predicate, selector);
}
public override IEnumerable<TSource> Where(Func<TSource, bool> predicate) {
return new WhereListIterator<TSource>(source, CombinePredicates(this.predicate, predicate));
}
}
/// <summary>
/// An iterator that maps each item of an <see cref="IEnumerable{TSource}"/>.
/// </summary>
/// <typeparam name="TSource">The type of the source enumerable.</typeparam>
/// <typeparam name="TResult">The type of the mapped items.</typeparam>
class SelectEnumerableIterator<TSource, TResult> : Iterator<TResult>, IIListProvider<TResult>
{
private readonly IEnumerable<TSource> _source;
private readonly Func<TSource, TResult> _selector;
private IEnumerator<TSource> _enumerator;
public SelectEnumerableIterator(IEnumerable<TSource> source, Func<TSource, TResult> selector)
{
_source = source;
_selector = selector;
}
public override Iterator<TResult> Clone()
{
return new SelectEnumerableIterator<TSource, TResult>(_source, _selector);
}
public override void Dispose()
{
if (_enumerator != null)
{
_enumerator.Dispose();
_enumerator = null;
}
base.Dispose();
}
public override bool MoveNext()
{
switch (state)
{
case 1:
_enumerator = _source.GetEnumerator();
state = 2;
goto case 2;
case 2:
if (_enumerator.MoveNext())
{
current = _selector(_enumerator.Current);
return true;
}
Dispose();
break;
}
return false;
}
public override IEnumerable<TResult2> Select<TResult2>(Func<TResult, TResult2> selector)
{
return new SelectEnumerableIterator<TSource, TResult2>(_source, CombineSelectors(_selector, selector));
}
public override IEnumerable<TResult> Where(Func<TResult, bool> predicate)
{
return new WhereEnumerableIterator<TResult>(this, predicate);
}
public TResult[] ToArray()
{
var builder = new LargeArrayBuilder<TResult>(initialize: true);
foreach (TSource item in _source)
{
builder.Add(_selector(item));
}
return builder.ToArray();
}
public List<TResult> ToList()
{
var list = new List<TResult>();
foreach (TSource item in _source)
{
list.Add(_selector(item));
}
return list;
}
public int GetCount(bool onlyIfCheap)
{
// In case someone uses Count() to force evaluation of
// the selector, run it provided `onlyIfCheap` is false.
if (onlyIfCheap)
{
return -1;
}
int count = 0;
foreach (TSource item in _source)
{
_selector(item);
checked
{
count++;
}
}
return count;
}
}
class WhereSelectEnumerableIterator<TSource, TResult> : Iterator<TResult>
{
IEnumerable<TSource> source;
Func<TSource, bool> predicate;
Func<TSource, TResult> selector;
IEnumerator<TSource> enumerator;
public WhereSelectEnumerableIterator(IEnumerable<TSource> source, Func<TSource, bool> predicate, Func<TSource, TResult> selector) {
this.source = source;
this.predicate = predicate;
this.selector = selector;
}
public override Iterator<TResult> Clone() {
return new WhereSelectEnumerableIterator<TSource, TResult>(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<TResult2> Select<TResult2>(Func<TResult, TResult2> selector) {
return new WhereSelectEnumerableIterator<TSource, TResult2>(source, predicate, CombineSelectors(this.selector, selector));
}
public override IEnumerable<TResult> Where(Func<TResult, bool> predicate) {
return new WhereEnumerableIterator<TResult>(this, predicate);
}
}
class WhereSelectArrayIterator<TSource, TResult> : Iterator<TResult>
{
TSource[] source;
Func<TSource, bool> predicate;
Func<TSource, TResult> selector;
int index;
public WhereSelectArrayIterator(TSource[] source, Func<TSource, bool> predicate, Func<TSource, TResult> selector) {
this.source = source;
this.predicate = predicate;
this.selector = selector;
}
public override Iterator<TResult> Clone() {
return new WhereSelectArrayIterator<TSource, TResult>(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<TResult2> Select<TResult2>(Func<TResult, TResult2> selector) {
return new WhereSelectArrayIterator<TSource, TResult2>(source, predicate, CombineSelectors(this.selector, selector));
}
public override IEnumerable<TResult> Where(Func<TResult, bool> predicate) {
return new WhereEnumerableIterator<TResult>(this, predicate);
}
}
class WhereSelectListIterator<TSource, TResult> : Iterator<TResult>
{
List<TSource> source;
Func<TSource, bool> predicate;
Func<TSource, TResult> selector;
List<TSource>.Enumerator enumerator;
public WhereSelectListIterator(List<TSource> source, Func<TSource, bool> predicate, Func<TSource, TResult> selector) {
this.source = source;
this.predicate = predicate;
this.selector = selector;
}
public override Iterator<TResult> Clone() {
return new WhereSelectListIterator<TSource, TResult>(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<TResult2> Select<TResult2>(Func<TResult, TResult2> selector) {
return new WhereSelectListIterator<TSource, TResult2>(source, predicate, CombineSelectors(this.selector, selector));
}
public override IEnumerable<TResult> Where(Func<TResult, bool> predicate) {
return new WhereEnumerableIterator<TResult>(this, predicate);
}
}
//public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
// if (source == null) throw Error.ArgumentNull("source");
// if (predicate == null) throw Error.ArgumentNull("predicate");
// return WhereIterator<TSource>(source, predicate);
//}
//static IEnumerable<TSource> WhereIterator<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate) {
// foreach (TSource element in source) {
// if (predicate(element)) yield return element;
// }
//}
//public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) {
// if (source == null) throw Error.ArgumentNull("source");
// if (selector == null) throw Error.ArgumentNull("selector");
// return SelectIterator<TSource, TResult>(source, selector);
//}
//static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector) {
// foreach (TSource element in source) {
// yield return selector(element);
// }
//}
public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector) {
if (source == null) throw Error.ArgumentNull("source");
if (selector == null) throw Error.ArgumentNull("selector");
return SelectManyIterator<TSource, TResult>(source, selector);
}
static IEnumerable<TResult> SelectManyIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector) {
foreach (TSource element in source) {
foreach (TResult subElement in selector(element)) {
yield return subElement;
}
}
}
public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector) {
if (source == null) throw Error.ArgumentNull("source");
if (selector == null) throw Error.ArgumentNull("selector");
return SelectManyIterator<TSource, TResult>(source, selector);
}
static IEnumerable<TResult> SelectManyIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector) {
int index = -1;
foreach (TSource element in source) {
checked { index++; }
foreach (TResult subElement in selector(element, index)) {
yield return subElement;
}
}
}
public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
{
if (source == null) throw Error.ArgumentNull("source");
if (collectionSelector == null) throw Error.ArgumentNull("collectionSelector");
if (resultSelector == null) throw Error.ArgumentNull("resultSelector");
return SelectManyIterator<TSource, TCollection, TResult>(source, collectionSelector, resultSelector);
}
static IEnumerable<TResult> SelectManyIterator<TSource, TCollection, TResult>(IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> 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<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector) {
if (source == null) throw Error.ArgumentNull("source");
if (collectionSelector == null) throw Error.ArgumentNull("collectionSelector");
if (resultSelector == null) throw Error.ArgumentNull("resultSelector");
return SelectManyIterator<TSource, TCollection, TResult>(source, collectionSelector, resultSelector);
}
static IEnumerable<TResult> SelectManyIterator<TSource, TCollection, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector) {
foreach (TSource element in source) {
foreach (TCollection subElement in collectionSelector(element)) {
yield return resultSelector(element, subElement);
}
}
}
public static IEnumerable<TSource> Take<TSource>(this IEnumerable<TSource> source, int count) {
if (source == null) throw Error.ArgumentNull("source");
return TakeIterator<TSource>(source, count);
}
static IEnumerable<TSource> TakeIterator<TSource>(IEnumerable<TSource> source, int count) {
if (count > 0) {
foreach (TSource element in source) {
yield return element;
if (--count == 0) break;
}
}
}
public static IEnumerable<TSource> TakeWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
return TakeWhileIterator<TSource>(source, predicate);
}
static IEnumerable<TSource> TakeWhileIterator<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate) {
foreach (TSource element in source) {
if (!predicate(element)) break;
yield return element;
}
}
public static IEnumerable<TSource> TakeWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
return TakeWhileIterator<TSource>(source, predicate);
}
static IEnumerable<TSource> TakeWhileIterator<TSource>(IEnumerable<TSource> source, Func<TSource, int, bool> predicate) {
int index = -1;
foreach (TSource element in source) {
checked { index++; }
if (!predicate(element, index)) break;
yield return element;
}
}
public static IEnumerable<TSource> Skip<TSource>(this IEnumerable<TSource> source, int count) {
if (source == null) throw Error.ArgumentNull("source");
return SkipIterator<TSource>(source, count);
}
static IEnumerable<TSource> SkipIterator<TSource>(IEnumerable<TSource> source, int count) {
using (IEnumerator<TSource> e = source.GetEnumerator()) {
while (count > 0 && e.MoveNext()) count--;
if (count <= 0) {
while (e.MoveNext()) yield return e.Current;
}
}
}
public static IEnumerable<TSource> SkipWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
return SkipWhileIterator<TSource>(source, predicate);
}
static IEnumerable<TSource> SkipWhileIterator<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate) {
bool yielding = false;
foreach (TSource element in source) {
if (!yielding && !predicate(element)) yielding = true;
if (yielding) yield return element;
}
}
public static IEnumerable<TSource> SkipWhile<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
return SkipWhileIterator<TSource>(source, predicate);
}
static IEnumerable<TSource> SkipWhileIterator<TSource>(IEnumerable<TSource> source, Func<TSource, int, bool> 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<TResult> Join<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, 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 JoinIterator<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
}
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> 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<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
}
static IEnumerable<TResult> JoinIterator<TOuter, TInner, TKey, TResult>(IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer) {
Lookup<TKey, TInner> lookup = Lookup<TKey, TInner>.CreateForJoin(inner, innerKeySelector, comparer);
foreach (TOuter item in outer) {
Lookup<TKey, TInner>.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<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, 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<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
}
public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> 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<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
}
static IEnumerable<TResult> GroupJoinIterator<TOuter, TInner, TKey, TResult>(IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer) {
Lookup<TKey, TInner> lookup = Lookup<TKey, TInner>.CreateForJoin(inner, innerKeySelector, comparer);
foreach (TOuter item in outer) {
yield return resultSelector(item, lookup[outerKeySelector(item)]);
}
}
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) {
return new OrderedEnumerable<TSource, TKey>(source, keySelector, null, false);
}
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) {
return new OrderedEnumerable<TSource, TKey>(source, keySelector, comparer, false);
}
public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) {
return new OrderedEnumerable<TSource, TKey>(source, keySelector, null, true);
}
public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) {
return new OrderedEnumerable<TSource, TKey>(source, keySelector, comparer, true);
}
public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector) {
if (source == null) throw Error.ArgumentNull("source");
return source.CreateOrderedEnumerable<TKey>(keySelector, null, false);
}
public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) {
if (source == null) throw Error.ArgumentNull("source");
return source.CreateOrderedEnumerable<TKey>(keySelector, comparer, false);
}
public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector) {
if (source == null) throw Error.ArgumentNull("source");
return source.CreateOrderedEnumerable<TKey>(keySelector, null, true);
}
public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) {
if (source == null) throw Error.ArgumentNull("source");
return source.CreateOrderedEnumerable<TKey>(keySelector, comparer, true);
}
public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) {
return new GroupedEnumerable<TSource, TKey, TSource>(source, keySelector, IdentityFunction<TSource>.Instance, null);
}
public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer) {
return new GroupedEnumerable<TSource, TKey, TSource>(source, keySelector, IdentityFunction<TSource>.Instance, comparer);
}
public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector) {
return new GroupedEnumerable<TSource, TKey, TElement>(source, keySelector, elementSelector, null);
}
public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer) {
return new GroupedEnumerable<TSource, TKey, TElement>(source, keySelector, elementSelector, comparer);
}
public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector){
return new GroupedEnumerable<TSource, TKey, TSource, TResult>(source, keySelector, IdentityFunction<TSource>.Instance, resultSelector, null);
}
public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector){
return new GroupedEnumerable<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, null);
}
public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey> comparer){
return new GroupedEnumerable<TSource, TKey, TSource, TResult>(source, keySelector, IdentityFunction<TSource>.Instance, resultSelector, comparer);
}
public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> comparer){
return new GroupedEnumerable<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, comparer);
}
public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return ConcatIterator<TSource>(first, second);
}
static IEnumerable<TSource> ConcatIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second) {
foreach (TSource element in first) yield return element;
foreach (TSource element in second) yield return element;
}
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> 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<TResult> ZipIterator<TFirst, TSecond, TResult>(IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector) {
using (IEnumerator<TFirst> e1 = first.GetEnumerator())
using (IEnumerator<TSecond> e2 = second.GetEnumerator())
while (e1.MoveNext() && e2.MoveNext())
yield return resultSelector(e1.Current, e2.Current);
}
public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
return DistinctIterator<TSource>(source, null);
}
public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer) {
if (source == null) throw Error.ArgumentNull("source");
return DistinctIterator<TSource>(source, comparer);
}
static IEnumerable<TSource> DistinctIterator<TSource>(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer) {
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource element in source)
if (set.Add(element)) yield return element;
}
public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return UnionIterator<TSource>(first, second, null);
}
public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return UnionIterator<TSource>(first, second, comparer);
}
static IEnumerable<TSource> UnionIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
Set<TSource> set = new Set<TSource>(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<TSource> Intersect<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return IntersectIterator<TSource>(first, second, null);
}
public static IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return IntersectIterator<TSource>(first, second, comparer);
}
static IEnumerable<TSource> IntersectIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource element in second) set.Add(element);
foreach (TSource element in first)
if (set.Remove(element)) yield return element;
}
public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
{
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return ExceptIterator<TSource>(first, second, null);
}
public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return ExceptIterator<TSource>(first, second, comparer);
}
static IEnumerable<TSource> ExceptIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer) {
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource element in second) set.Add(element);
foreach (TSource element in first)
if (set.Add(element)) yield return element;
}
public static IEnumerable<TSource> Reverse<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
return ReverseIterator<TSource>(source);
}
static IEnumerable<TSource> ReverseIterator<TSource>(IEnumerable<TSource> source) {
Buffer<TSource> buffer = new Buffer<TSource>(source);
for (int i = buffer.count - 1; i >= 0; i--) yield return buffer.items[i];
}
public static bool SequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
return SequenceEqual<TSource>(first, second, null);
}
public static bool SequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
if (comparer == null) comparer = EqualityComparer<TSource>.Default;
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
using (IEnumerator<TSource> e1 = first.GetEnumerator())
using (IEnumerator<TSource> 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<TSource> AsEnumerable<TSource>(this IEnumerable<TSource> source)
{
return source;
}
public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
return new Buffer<TSource>(source).ToArray();
}
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
return new List<TSource>(source);
}
public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) {
return ToDictionary<TSource, TKey, TSource>(source, keySelector, IdentityFunction<TSource>.Instance, null);
}
public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer) {
return ToDictionary<TSource, TKey, TSource>(source, keySelector, IdentityFunction<TSource>.Instance, comparer);
}
public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector) {
return ToDictionary<TSource, TKey, TElement>(source, keySelector, elementSelector, null);
}
public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer) {
if (source == null) throw Error.ArgumentNull("source");
if (keySelector == null) throw Error.ArgumentNull("keySelector");
if (elementSelector == null) throw Error.ArgumentNull("elementSelector");
Dictionary<TKey, TElement> d = new Dictionary<TKey, TElement>(comparer);
foreach (TSource element in source) d.Add(keySelector(element), elementSelector(element));
return d;
}
public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) {
return Lookup<TKey, TSource>.Create(source, keySelector, IdentityFunction<TSource>.Instance, null);
}
public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer) {
return Lookup<TKey, TSource>.Create(source, keySelector, IdentityFunction<TSource>.Instance, comparer);
}
public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector) {
return Lookup<TKey, TElement>.Create(source, keySelector, elementSelector, null);
}
public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer) {
return Lookup<TKey, TElement>.Create(source, keySelector, elementSelector, comparer);
}
public static HashSet<TSource> ToHashSet<TSource>(this IEnumerable<TSource> source) {
return source.ToHashSet(null);
}
public static HashSet<TSource> ToHashSet<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer) {
if (source == null) throw Error.ArgumentNull("source");
return new HashSet<TSource>(source, comparer);
}
public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source) {
return DefaultIfEmpty(source, default(TSource));
}
public static IEnumerable<TSource> DefaultIfEmpty<TSource>(this IEnumerable<TSource> source, TSource defaultValue) {
if (source == null) throw Error.ArgumentNull("source");
return DefaultIfEmptyIterator<TSource>(source, defaultValue);
}
static IEnumerable<TSource> DefaultIfEmptyIterator<TSource>(IEnumerable<TSource> source, TSource defaultValue) {
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) {
do {
yield return e.Current;
} while (e.MoveNext());
}
else {
yield return defaultValue;
}
}
}
public static IEnumerable<TResult> OfType<TResult>(this IEnumerable source) {
if (source == null) throw Error.ArgumentNull("source");
return OfTypeIterator<TResult>(source);
}
static IEnumerable<TResult> OfTypeIterator<TResult>(IEnumerable source) {
foreach (object obj in source) {
if (obj is TResult) yield return (TResult)obj;
}
}
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) {
IEnumerable<TResult> typedSource = source as IEnumerable<TResult>;
if (typedSource != null) return typedSource;
if (source == null) throw Error.ArgumentNull("source");
return CastIterator<TResult>(source);
}
static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source) {
foreach (object obj in source) yield return (TResult)obj;
}
public static TSource First<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
IList<TSource> list = source as IList<TSource>;
if (list != null) {
if (list.Count > 0) return list[0];
}
else {
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) return e.Current;
}
}
throw Error.NoElements();
}
public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> 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<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
IList<TSource> list = source as IList<TSource>;
if (list != null) {
if (list.Count > 0) return list[0];
}
else {
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) return e.Current;
}
}
return default(TSource);
}
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> 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<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
IList<TSource> list = source as IList<TSource>;
if (list != null) {
int count = list.Count;
if (count > 0) return list[count - 1];
}
else {
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) {
TSource result;
do {
result = e.Current;
} while (e.MoveNext());
return result;
}
}
}
throw Error.NoElements();
}
public static TSource Last<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> 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<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
IList<TSource> list = source as IList<TSource>;
if (list != null) {
int count = list.Count;
if (count > 0) return list[count - 1];
}
else {
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) {
TSource result;
do {
result = e.Current;
} while (e.MoveNext());
return result;
}
}
}
return default(TSource);
}
public static TSource LastOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> 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<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
IList<TSource> list = source as IList<TSource>;
if (list != null) {
switch (list.Count) {
case 0: throw Error.NoElements();
case 1: return list[0];
}
}
else {
using (IEnumerator<TSource> 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<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> 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<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
IList<TSource> list = source as IList<TSource>;
if (list != null) {
switch (list.Count) {
case 0: return default(TSource);
case 1: return list[0];
}
}
else {
using (IEnumerator<TSource> 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<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> 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<TSource>(this IEnumerable<TSource> source, int index) {
if (source == null) throw Error.ArgumentNull("source");
IList<TSource> list = source as IList<TSource>;
if (list != null) return list[index];
if (index < 0) throw Error.ArgumentOutOfRange("index");
using (IEnumerator<TSource> e = source.GetEnumerator()) {
while (true) {
if (!e.MoveNext()) throw Error.ArgumentOutOfRange("index");
if (index == 0) return e.Current;
index--;
}
}
}
public static TSource ElementAtOrDefault<TSource>(this IEnumerable<TSource> source, int index) {
if (source == null) throw Error.ArgumentNull("source");
if (index >= 0) {
IList<TSource> list = source as IList<TSource>;
if (list != null) {
if (index < list.Count) return list[index];
}
else {
using (IEnumerator<TSource> e = source.GetEnumerator()) {
while (true) {
if (!e.MoveNext()) break;
if (index == 0) return e.Current;
index--;
}
}
}
}
return default(TSource);
}
public static IEnumerable<int> 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<int> RangeIterator(int start, int count) {
for (int i = 0; i < count; i++) yield return start + i;
}
public static IEnumerable<TResult> Repeat<TResult>(TResult element, int count) {
if (count < 0) throw Error.ArgumentOutOfRange("count");
return RepeatIterator<TResult>(element, count);
}
static IEnumerable<TResult> RepeatIterator<TResult>(TResult element, int count) {
for (int i = 0; i < count; i++) yield return element;
}
public static IEnumerable<TResult> Empty<TResult>() {
return EmptyEnumerable<TResult>.Instance;
}
public static bool Any<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) return true;
}
return false;
}
public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> 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<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> 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<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
ICollection<TSource> collectionoft = source as ICollection<TSource>;
if (collectionoft != null) return collectionoft.Count;
ICollection collection = source as ICollection;
if (collection != null) return collection.Count;
int count = 0;
using (IEnumerator<TSource> e = source.GetEnumerator()) {
checked {
while (e.MoveNext()) count++;
}
}
return count;
}
public static int Count<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> 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<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
long count = 0;
using (IEnumerator<TSource> e = source.GetEnumerator()) {
checked {
while (e.MoveNext()) count++;
}
}
return count;
}
public static long LongCount<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> 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<TSource>(this IEnumerable<TSource> source, TSource value) {
ICollection<TSource> collection = source as ICollection<TSource>;
if (collection != null) return collection.Contains(value);
return Contains<TSource>(source, value, null);
}
public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
{
if (comparer == null) comparer = EqualityComparer<TSource>.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<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func)
{
if (source == null) throw Error.ArgumentNull("source");
if (func == null) throw Error.ArgumentNull("func");
using (IEnumerator<TSource> 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<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> 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<TSource, TAccumulate, TResult>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> 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<int> 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<int?> 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<long> 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<long?> 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<float> 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<float?> 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<double> 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<double?> 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<decimal> 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<decimal?> 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<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector) {
return Enumerable.Sum(Enumerable.Select(source, selector));
}
public static int? Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, int?> selector) {
return Enumerable.Sum(Enumerable.Select(source, selector));
}
public static long Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, long> selector) {
return Enumerable.Sum(Enumerable.Select(source, selector));
}
public static long? Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, long?> selector) {
return Enumerable.Sum(Enumerable.Select(source, selector));
}
public static float Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, float> selector) {
return Enumerable.Sum(Enumerable.Select(source, selector));
}
public static float? Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, float?> selector) {
return Enumerable.Sum(Enumerable.Select(source, selector));
}
public static double Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector) {
return Enumerable.Sum(Enumerable.Select(source, selector));
}
public static double? Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, double?> selector) {
return Enumerable.Sum(Enumerable.Select(source, selector));
}
public static decimal Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal> selector) {
return Enumerable.Sum(Enumerable.Select(source, selector));
}
public static decimal? Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal?> selector) {
return Enumerable.Sum(Enumerable.Select(source, selector));
}
public static int Min(this IEnumerable<int> 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<int?> 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<long> 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<long?> 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<float> 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<float?> 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<double> 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<double?> 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<decimal> 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<decimal?> 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<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
Comparer<TSource> comparer = Comparer<TSource>.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<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector) {
return Enumerable.Min(Enumerable.Select(source, selector));
}
public static int? Min<TSource>(this IEnumerable<TSource> source, Func<TSource, int?> selector) {
return Enumerable.Min(Enumerable.Select(source, selector));
}
public static long Min<TSource>(this IEnumerable<TSource> source, Func<TSource, long> selector) {
return Enumerable.Min(Enumerable.Select(source, selector));
}
public static long? Min<TSource>(this IEnumerable<TSource> source, Func<TSource, long?> selector) {
return Enumerable.Min(Enumerable.Select(source, selector));
}
public static float Min<TSource>(this IEnumerable<TSource> source, Func<TSource, float> selector) {
return Enumerable.Min(Enumerable.Select(source, selector));
}
public static float? Min<TSource>(this IEnumerable<TSource> source, Func<TSource, float?> selector) {
return Enumerable.Min(Enumerable.Select(source, selector));
}
public static double Min<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector) {
return Enumerable.Min(Enumerable.Select(source, selector));
}
public static double? Min<TSource>(this IEnumerable<TSource> source, Func<TSource, double?> selector) {
return Enumerable.Min(Enumerable.Select(source, selector));
}
public static decimal Min<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal> selector) {
return Enumerable.Min(Enumerable.Select(source, selector));
}
public static decimal? Min<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal?> selector) {
return Enumerable.Min(Enumerable.Select(source, selector));
}
public static TResult Min<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) {
return Enumerable.Min(Enumerable.Select(source, selector));
}
public static int Max(this IEnumerable<int> 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<int?> 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<long> 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<long?> 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<double> 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<double?> 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<float> 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<float?> 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<decimal> 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<decimal?> 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<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
Comparer<TSource> comparer = Comparer<TSource>.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<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector) {
return Enumerable.Max(Enumerable.Select(source, selector));
}
public static int? Max<TSource>(this IEnumerable<TSource> source, Func<TSource, int?> selector) {
return Enumerable.Max(Enumerable.Select(source, selector));
}
public static long Max<TSource>(this IEnumerable<TSource> source, Func<TSource, long> selector) {
return Enumerable.Max(Enumerable.Select(source, selector));
}
public static long? Max<TSource>(this IEnumerable<TSource> source, Func<TSource, long?> selector) {
return Enumerable.Max(Enumerable.Select(source, selector));
}
public static float Max<TSource>(this IEnumerable<TSource> source, Func<TSource, float> selector) {
return Enumerable.Max(Enumerable.Select(source, selector));
}
public static float? Max<TSource>(this IEnumerable<TSource> source, Func<TSource, float?> selector) {
return Enumerable.Max(Enumerable.Select(source, selector));
}
public static double Max<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector) {
return Enumerable.Max(Enumerable.Select(source, selector));
}
public static double? Max<TSource>(this IEnumerable<TSource> source, Func<TSource, double?> selector) {
return Enumerable.Max(Enumerable.Select(source, selector));
}
public static decimal Max<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal> selector) {
return Enumerable.Max(Enumerable.Select(source, selector));
}
public static decimal? Max<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal?> selector) {
return Enumerable.Max(Enumerable.Select(source, selector));
}
public static TResult Max<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector) {
return Enumerable.Max(Enumerable.Select(source, selector));
}
public static double Average(this IEnumerable<int> 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<int?> 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<long> 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<long?> 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<float> 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<float?> 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<double> 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<double?> 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<decimal> 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<decimal?> 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<TSource>(this IEnumerable<TSource> source, Func<TSource, int> selector) {
return Enumerable.Average(Enumerable.Select(source, selector));
}
public static double? Average<TSource>(this IEnumerable<TSource> source, Func<TSource, int?> selector) {
return Enumerable.Average(Enumerable.Select(source, selector));
}
public static double Average<TSource>(this IEnumerable<TSource> source, Func<TSource, long> selector) {
return Enumerable.Average(Enumerable.Select(source, selector));
}
public static double? Average<TSource>(this IEnumerable<TSource> source, Func<TSource, long?> selector) {
return Enumerable.Average(Enumerable.Select(source, selector));
}
public static float Average<TSource>(this IEnumerable<TSource> source, Func<TSource, float> selector) {
return Enumerable.Average(Enumerable.Select(source, selector));
}
public static float? Average<TSource>(this IEnumerable<TSource> source, Func<TSource, float?> selector) {
return Enumerable.Average(Enumerable.Select(source, selector));
}
public static double Average<TSource>(this IEnumerable<TSource> source, Func<TSource, double> selector) {
return Enumerable.Average(Enumerable.Select(source, selector));
}
public static double? Average<TSource>(this IEnumerable<TSource> source, Func<TSource, double?> selector) {
return Enumerable.Average(Enumerable.Select(source, selector));
}
public static decimal Average<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal> selector) {
return Enumerable.Average(Enumerable.Select(source, selector));
}
public static decimal? Average<TSource>(this IEnumerable<TSource> source, Func<TSource, decimal?> selector) {
return Enumerable.Average(Enumerable.Select(source, selector));
}
}
//
// We have added some optimization in SZArrayHelper class to cache the enumerator of zero length arrays so
// the enumerator will be created once per type.
//
internal class EmptyEnumerable<TElement>
{
public static readonly TElement[] Instance = new TElement[0];
}
internal class IdentityFunction<TElement>
{
public static Func<TElement, TElement> Instance {
get { return x => x; }
}
}
public interface IOrderedEnumerable<TElement> : IEnumerable<TElement>
{
IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending);
}
#if SILVERLIGHT && !FEATURE_NETCORE
public interface IGrouping<TKey, TElement> : IEnumerable<TElement>
#else
public interface IGrouping<out TKey, out TElement> : IEnumerable<TElement>
#endif
{
TKey Key { get; }
}
public interface ILookup<TKey, TElement> : IEnumerable<IGrouping<TKey, TElement>>{
int Count { get; }
IEnumerable<TElement> this[TKey key] { get; }
bool Contains(TKey key);
}
public class Lookup<TKey, TElement> : IEnumerable<IGrouping<TKey, TElement>>, ILookup<TKey, TElement>{
IEqualityComparer<TKey> comparer;
Grouping[] groupings;
Grouping lastGrouping;
int count;
internal static Lookup<TKey, TElement> Create<TSource>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer) {
if (source == null) throw Error.ArgumentNull("source");
if (keySelector == null) throw Error.ArgumentNull("keySelector");
if (elementSelector == null) throw Error.ArgumentNull("elementSelector");
Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
foreach (TSource item in source) {
lookup.GetGrouping(keySelector(item), true).Add(elementSelector(item));
}
return lookup;
}
internal static Lookup<TKey, TElement> CreateForJoin(IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer) {
Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
foreach (TElement item in source) {
TKey key = keySelector(item);
if (key != null) lookup.GetGrouping(key, true).Add(item);
}
return lookup;
}
Lookup(IEqualityComparer<TKey> comparer) {
if (comparer == null) comparer = EqualityComparer<TKey>.Default;
this.comparer = comparer;
groupings = new Grouping[7];
}
public int Count {
get { return count; }
}
public IEnumerable<TElement> this[TKey key] {
get {
Grouping grouping = GetGrouping(key, false);
if (grouping != null) return grouping;
return EmptyEnumerable<TElement>.Instance;
}
}
public bool Contains(TKey key) {
return GetGrouping(key, false) != null;
}
public IEnumerator<IGrouping<TKey, TElement>> GetEnumerator() {
Grouping g = lastGrouping;
if (g != null) {
do {
g = g.next;
yield return g;
} while (g != lastGrouping);
}
}
public IEnumerable<TResult> ApplyResultSelector<TResult>(Func<TKey, IEnumerable<TElement>, TResult> resultSelector){
Grouping g = lastGrouping;
if (g != null) {
do {
g = g.next;
if (g.count != g.elements.Length) { Array.Resize<TElement>(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)
{
//Microsoft 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<TKey, TElement>, IList<TElement>
{
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<TElement> 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<TElement>.Count {
get { return count; }
}
bool ICollection<TElement>.IsReadOnly {
get { return true; }
}
void ICollection<TElement>.Add(TElement item) {
throw Error.NotSupported();
}
void ICollection<TElement>.Clear() {
throw Error.NotSupported();
}
bool ICollection<TElement>.Contains(TElement item) {
return Array.IndexOf(elements, item, 0, count) >= 0;
}
void ICollection<TElement>.CopyTo(TElement[] array, int arrayIndex) {
Array.Copy(elements, 0, array, arrayIndex, count);
}
bool ICollection<TElement>.Remove(TElement item) {
throw Error.NotSupported();
}
int IList<TElement>.IndexOf(TElement item) {
return Array.IndexOf(elements, item, 0, count);
}
void IList<TElement>.Insert(int index, TElement item) {
throw Error.NotSupported();
}
void IList<TElement>.RemoveAt(int index) {
throw Error.NotSupported();
}
TElement IList<TElement>.this[int index] {
get {
if (index < 0 || index >= count) throw Error.ArgumentOutOfRange("index");
return elements[index];
}
set {
throw Error.NotSupported();
}
}
}
}
// @
internal class Set<TElement>
{
int[] buckets;
Slot[] slots;
int count;
int freeList;
IEqualityComparer<TElement> comparer;
public Set() : this(null) { }
public Set(IEqualityComparer<TElement> comparer) {
if (comparer == null) comparer = EqualityComparer<TElement>.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)
{
//Microsoft 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<TSource, TKey, TElement, TResult> : IEnumerable<TResult>{
IEnumerable<TSource> source;
Func<TSource, TKey> keySelector;
Func<TSource, TElement> elementSelector;
IEqualityComparer<TKey> comparer;
Func<TKey, IEnumerable<TElement>, TResult> resultSelector;
public GroupedEnumerable(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> 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<TResult> GetEnumerator(){
Lookup<TKey, TElement> lookup = Lookup<TKey, TElement>.Create<TSource>(source, keySelector, elementSelector, comparer);
return lookup.ApplyResultSelector(resultSelector).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator(){
return GetEnumerator();
}
}
internal class GroupedEnumerable<TSource, TKey, TElement> : IEnumerable<IGrouping<TKey, TElement>>
{
IEnumerable<TSource> source;
Func<TSource, TKey> keySelector;
Func<TSource, TElement> elementSelector;
IEqualityComparer<TKey> comparer;
public GroupedEnumerable(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> 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<IGrouping<TKey, TElement>> GetEnumerator() {
return Lookup<TKey, TElement>.Create<TSource>(source, keySelector, elementSelector, comparer).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
internal abstract class OrderedEnumerable<TElement> : IOrderedEnumerable<TElement>
{
internal IEnumerable<TElement> source;
public IEnumerator<TElement> GetEnumerator() {
Buffer<TElement> buffer = new Buffer<TElement>(source);
if (buffer.count > 0) {
EnumerableSorter<TElement> 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<TElement> GetEnumerableSorter(EnumerableSorter<TElement> next);
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
IOrderedEnumerable<TElement> IOrderedEnumerable<TElement>.CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending) {
OrderedEnumerable<TElement, TKey> result = new OrderedEnumerable<TElement, TKey>(source, keySelector, comparer, descending);
result.parent = this;
return result;
}
}
internal class OrderedEnumerable<TElement, TKey> : OrderedEnumerable<TElement>
{
internal OrderedEnumerable<TElement> parent;
internal Func<TElement, TKey> keySelector;
internal IComparer<TKey> comparer;
internal bool descending;
internal OrderedEnumerable(IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IComparer<TKey> 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<TKey>.Default;
this.descending = descending;
}
internal override EnumerableSorter<TElement> GetEnumerableSorter(EnumerableSorter<TElement> next) {
EnumerableSorter<TElement> sorter = new EnumerableSorter<TElement, TKey>(keySelector, comparer, descending, next);
if (parent != null) sorter = parent.GetEnumerableSorter(sorter);
return sorter;
}
}
internal abstract class EnumerableSorter<TElement>
{
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<TElement, TKey> : EnumerableSorter<TElement>
{
internal Func<TElement, TKey> keySelector;
internal IComparer<TKey> comparer;
internal bool descending;
internal EnumerableSorter<TElement> next;
internal TKey[] keys;
internal EnumerableSorter(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending, EnumerableSorter<TElement> 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<TElement>
{
internal TElement[] items;
internal int count;
internal Buffer(IEnumerable<TElement> source) {
TElement[] items = null;
int count = 0;
ICollection<TElement> collection = source as ICollection<TElement>;
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;
}
}
/// <summary>
/// This class provides the items view for the Enumerable
/// </summary>
/// <typeparam name="T"></typeparam>
internal sealed class SystemCore_EnumerableDebugView<T>
{
public SystemCore_EnumerableDebugView(IEnumerable<T> enumerable)
{
if (enumerable == null)
{
throw new ArgumentNullException("enumerable");
}
this.enumerable = enumerable;
}
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
public T[] Items
{
get
{
List<T> tempList = new List<T>();
IEnumerator<T> 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<T> 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<object> tempList = new List<object>();
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;
}
}