Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / Linq / Enumerable.cs / 1407647 / Enumerable.cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
// Include Silverlight's managed resources
#if SILVERLIGHT
using System.Core;
#endif //SILVERLIGHT
namespace System.Linq
{
public static class Enumerable
{
public static IEnumerable Where(this IEnumerable source, Func predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
if (source is Iterator) return ((Iterator)source).Where(predicate);
if (source is TSource[]) return new WhereArrayIterator((TSource[])source, predicate);
if (source is List) return new WhereListIterator((List)source, predicate);
return new WhereEnumerableIterator(source, predicate);
}
public static IEnumerable Where(this IEnumerable source, Func predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
return WhereIterator(source, predicate);
}
static IEnumerable WhereIterator(IEnumerable source, Func predicate) {
int index = -1;
foreach (TSource element in source) {
checked { index++; }
if (predicate(element, index)) yield return element;
}
}
public static IEnumerable Select(this IEnumerable source, Func selector) {
if (source == null) throw Error.ArgumentNull("source");
if (selector == null) throw Error.ArgumentNull("selector");
if (source is Iterator) return ((Iterator)source).Select(selector);
if (source is TSource[]) return new WhereSelectArrayIterator((TSource[])source, null, selector);
if (source is List) return new WhereSelectListIterator((List)source, null, selector);
return new WhereSelectEnumerableIterator(source, null, selector);
}
public static IEnumerable Select(this IEnumerable source, Func selector) {
if (source == null) throw Error.ArgumentNull("source");
if (selector == null) throw Error.ArgumentNull("selector");
return SelectIterator(source, selector);
}
static IEnumerable SelectIterator(IEnumerable source, Func selector) {
int index = -1;
foreach (TSource element in source) {
checked { index++; }
yield return selector(element, index);
}
}
static Func CombinePredicates(Func predicate1, Func predicate2) {
return x => predicate1(x) && predicate2(x);
}
static Func CombineSelectors(Func selector1, Func selector2) {
return x => selector2(selector1(x));
}
abstract class Iterator : IEnumerable, IEnumerator
{
int threadId;
internal int state;
internal TSource current;
public Iterator() {
threadId = Thread.CurrentThread.ManagedThreadId;
}
public TSource Current {
get { return current; }
}
public abstract Iterator Clone();
public virtual void Dispose() {
current = default(TSource);
state = -1;
}
public IEnumerator GetEnumerator() {
if (threadId == Thread.CurrentThread.ManagedThreadId && state == 0) {
state = 1;
return this;
}
Iterator duplicate = Clone();
duplicate.state = 1;
return duplicate;
}
public abstract bool MoveNext();
public abstract IEnumerable Select(Func selector);
public abstract IEnumerable Where(Func predicate);
object IEnumerator.Current {
get { return Current; }
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
void IEnumerator.Reset() {
throw new NotImplementedException();
}
}
class WhereEnumerableIterator : Iterator
{
IEnumerable source;
Func predicate;
IEnumerator enumerator;
public WhereEnumerableIterator(IEnumerable source, Func predicate) {
this.source = source;
this.predicate = predicate;
}
public override Iterator Clone() {
return new WhereEnumerableIterator(source, predicate);
}
public override void Dispose() {
if (enumerator is IDisposable) ((IDisposable)enumerator).Dispose();
enumerator = null;
base.Dispose();
}
public override bool MoveNext() {
switch (state) {
case 1:
enumerator = source.GetEnumerator();
state = 2;
goto case 2;
case 2:
while (enumerator.MoveNext()) {
TSource item = enumerator.Current;
if (predicate(item)) {
current = item;
return true;
}
}
Dispose();
break;
}
return false;
}
public override IEnumerable Select(Func selector) {
return new WhereSelectEnumerableIterator(source, predicate, selector);
}
public override IEnumerable Where(Func predicate) {
return new WhereEnumerableIterator(source, CombinePredicates(this.predicate, predicate));
}
}
class WhereArrayIterator : Iterator
{
TSource[] source;
Func predicate;
int index;
public WhereArrayIterator(TSource[] source, Func predicate) {
this.source = source;
this.predicate = predicate;
}
public override Iterator Clone() {
return new WhereArrayIterator(source, predicate);
}
public override bool MoveNext() {
if (state == 1) {
while (index < source.Length) {
TSource item = source[index];
index++;
if (predicate(item)) {
current = item;
return true;
}
}
Dispose();
}
return false;
}
public override IEnumerable Select(Func selector) {
return new WhereSelectArrayIterator(source, predicate, selector);
}
public override IEnumerable Where(Func predicate) {
return new WhereArrayIterator(source, CombinePredicates(this.predicate, predicate));
}
}
class WhereListIterator : Iterator
{
List source;
Func predicate;
List.Enumerator enumerator;
public WhereListIterator(List source, Func predicate) {
this.source = source;
this.predicate = predicate;
}
public override Iterator Clone() {
return new WhereListIterator(source, predicate);
}
public override bool MoveNext() {
switch (state) {
case 1:
enumerator = source.GetEnumerator();
state = 2;
goto case 2;
case 2:
while (enumerator.MoveNext()) {
TSource item = enumerator.Current;
if (predicate(item)) {
current = item;
return true;
}
}
Dispose();
break;
}
return false;
}
public override IEnumerable Select(Func selector) {
return new WhereSelectListIterator(source, predicate, selector);
}
public override IEnumerable Where(Func predicate) {
return new WhereListIterator(source, CombinePredicates(this.predicate, predicate));
}
}
class WhereSelectEnumerableIterator : Iterator
{
IEnumerable source;
Func predicate;
Func selector;
IEnumerator enumerator;
public WhereSelectEnumerableIterator(IEnumerable source, Func predicate, Func selector) {
this.source = source;
this.predicate = predicate;
this.selector = selector;
}
public override Iterator Clone() {
return new WhereSelectEnumerableIterator(source, predicate, selector);
}
public override void Dispose() {
if (enumerator is IDisposable) ((IDisposable)enumerator).Dispose();
enumerator = null;
base.Dispose();
}
public override bool MoveNext() {
switch (state) {
case 1:
enumerator = source.GetEnumerator();
state = 2;
goto case 2;
case 2:
while (enumerator.MoveNext()) {
TSource item = enumerator.Current;
if (predicate == null || predicate(item)) {
current = selector(item);
return true;
}
}
Dispose();
break;
}
return false;
}
public override IEnumerable Select(Func selector) {
return new WhereSelectEnumerableIterator(source, predicate, CombineSelectors(this.selector, selector));
}
public override IEnumerable Where(Func predicate) {
return new WhereEnumerableIterator(this, predicate);
}
}
class WhereSelectArrayIterator : Iterator
{
TSource[] source;
Func predicate;
Func selector;
int index;
public WhereSelectArrayIterator(TSource[] source, Func predicate, Func selector) {
this.source = source;
this.predicate = predicate;
this.selector = selector;
}
public override Iterator Clone() {
return new WhereSelectArrayIterator(source, predicate, selector);
}
public override bool MoveNext() {
if (state == 1) {
while (index < source.Length) {
TSource item = source[index];
index++;
if (predicate == null || predicate(item)) {
current = selector(item);
return true;
}
}
Dispose();
}
return false;
}
public override IEnumerable Select(Func selector) {
return new WhereSelectArrayIterator(source, predicate, CombineSelectors(this.selector, selector));
}
public override IEnumerable Where(Func predicate) {
return new WhereEnumerableIterator(this, predicate);
}
}
class WhereSelectListIterator : Iterator
{
List source;
Func predicate;
Func selector;
List.Enumerator enumerator;
public WhereSelectListIterator(List source, Func predicate, Func selector) {
this.source = source;
this.predicate = predicate;
this.selector = selector;
}
public override Iterator Clone() {
return new WhereSelectListIterator(source, predicate, selector);
}
public override bool MoveNext() {
switch (state) {
case 1:
enumerator = source.GetEnumerator();
state = 2;
goto case 2;
case 2:
while (enumerator.MoveNext()) {
TSource item = enumerator.Current;
if (predicate == null || predicate(item)) {
current = selector(item);
return true;
}
}
Dispose();
break;
}
return false;
}
public override IEnumerable Select(Func selector) {
return new WhereSelectListIterator(source, predicate, CombineSelectors(this.selector, selector));
}
public override IEnumerable Where(Func predicate) {
return new WhereEnumerableIterator(this, predicate);
}
}
//public static IEnumerable Where(this IEnumerable source, Func predicate) {
// if (source == null) throw Error.ArgumentNull("source");
// if (predicate == null) throw Error.ArgumentNull("predicate");
// return WhereIterator(source, predicate);
//}
//static IEnumerable WhereIterator(IEnumerable source, Func predicate) {
// foreach (TSource element in source) {
// if (predicate(element)) yield return element;
// }
//}
//public static IEnumerable Select(this IEnumerable source, Func selector) {
// if (source == null) throw Error.ArgumentNull("source");
// if (selector == null) throw Error.ArgumentNull("selector");
// return SelectIterator(source, selector);
//}
//static IEnumerable SelectIterator(IEnumerable source, Func selector) {
// foreach (TSource element in source) {
// yield return selector(element);
// }
//}
public static IEnumerable SelectMany(this IEnumerable source, Func> selector) {
if (source == null) throw Error.ArgumentNull("source");
if (selector == null) throw Error.ArgumentNull("selector");
return SelectManyIterator(source, selector);
}
static IEnumerable SelectManyIterator(IEnumerable source, Func> selector) {
foreach (TSource element in source) {
foreach (TResult subElement in selector(element)) {
yield return subElement;
}
}
}
public static IEnumerable SelectMany(this IEnumerable source, Func> selector) {
if (source == null) throw Error.ArgumentNull("source");
if (selector == null) throw Error.ArgumentNull("selector");
return SelectManyIterator(source, selector);
}
static IEnumerable SelectManyIterator(IEnumerable source, Func> selector) {
int index = -1;
foreach (TSource element in source) {
checked { index++; }
foreach (TResult subElement in selector(element, index)) {
yield return subElement;
}
}
}
public static IEnumerable SelectMany(this IEnumerable source, Func> collectionSelector, Func resultSelector)
{
if (source == null) throw Error.ArgumentNull("source");
if (collectionSelector == null) throw Error.ArgumentNull("collectionSelector");
if (resultSelector == null) throw Error.ArgumentNull("resultSelector");
return SelectManyIterator(source, collectionSelector, resultSelector);
}
static IEnumerable SelectManyIterator(IEnumerable source, Func> collectionSelector, Func resultSelector){
int index = -1;
foreach (TSource element in source){
checked { index++; }
foreach (TCollection subElement in collectionSelector(element, index)){
yield return resultSelector(element, subElement);
}
}
}
public static IEnumerable SelectMany(this IEnumerable source, Func> collectionSelector, Func resultSelector) {
if (source == null) throw Error.ArgumentNull("source");
if (collectionSelector == null) throw Error.ArgumentNull("collectionSelector");
if (resultSelector == null) throw Error.ArgumentNull("resultSelector");
return SelectManyIterator(source, collectionSelector, resultSelector);
}
static IEnumerable SelectManyIterator(IEnumerable source, Func> collectionSelector, Func resultSelector) {
foreach (TSource element in source) {
foreach (TCollection subElement in collectionSelector(element)) {
yield return resultSelector(element, subElement);
}
}
}
public static IEnumerable Take(this IEnumerable source, int count) {
if (source == null) throw Error.ArgumentNull("source");
return TakeIterator(source, count);
}
static IEnumerable TakeIterator(IEnumerable source, int count) {
if (count > 0) {
foreach (TSource element in source) {
yield return element;
if (--count == 0) break;
}
}
}
public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
return TakeWhileIterator(source, predicate);
}
static IEnumerable TakeWhileIterator(IEnumerable source, Func predicate) {
foreach (TSource element in source) {
if (!predicate(element)) break;
yield return element;
}
}
public static IEnumerable TakeWhile(this IEnumerable source, Func predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
return TakeWhileIterator(source, predicate);
}
static IEnumerable TakeWhileIterator(IEnumerable source, Func predicate) {
int index = -1;
foreach (TSource element in source) {
checked { index++; }
if (!predicate(element, index)) break;
yield return element;
}
}
public static IEnumerable Skip(this IEnumerable source, int count) {
if (source == null) throw Error.ArgumentNull("source");
return SkipIterator(source, count);
}
static IEnumerable SkipIterator(IEnumerable source, int count) {
using (IEnumerator e = source.GetEnumerator()) {
while (count > 0 && e.MoveNext()) count--;
if (count <= 0) {
while (e.MoveNext()) yield return e.Current;
}
}
}
public static IEnumerable SkipWhile(this IEnumerable source, Func