Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
2 contributors

Users who have contributed to this file

@dotnet-bot @rbhanda
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;
}