using System; using System.Collections.Generic; using System.Text; #region Extension Methods for .NET 2 #if NET2 // you need this once (only), and it must be in this namespace namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] public sealed class ExtensionAttribute : Attribute { } } #endif #endregion #region LINQBridge - LINQ for .NET 2 #if NET2 // LINQBridge // Atif Aziz, Joseph Albahari. All rights reserved. namespace System.Linq { #region Imports using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using LinqBridge; #endregion /// /// Provides a set of static (Shared in Visual Basic) methods for /// querying objects that implement . /// static partial class Enumerable { /// /// Returns the input typed as . /// public static IEnumerable AsEnumerable(this IEnumerable source) { return source; } /// /// Returns an empty that has the /// specified type argument. /// public static IEnumerable Empty() { return Sequence.Empty; } /// /// Converts the elements of an to the /// specified type. /// public static IEnumerable Cast( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return CastYield(source); } private static IEnumerable CastYield( IEnumerable source) { foreach (var item in source) yield return (TResult)item; } /// /// Filters the elements of an based on a specified type. /// public static IEnumerable OfType( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return OfTypeYield(source); } private static IEnumerable OfTypeYield( IEnumerable source) { foreach (var item in source) if (item is TResult) yield return (TResult)item; } /// /// Generates a sequence of integral numbers within a specified range. /// /// The value of the first integer in the sequence. /// The number of sequential integers to generate. public static IEnumerable Range(int start, int count) { if (count < 0) throw new ArgumentOutOfRangeException("count", count, null); var end = (long)start + count; if (end - 1 >= int.MaxValue) throw new ArgumentOutOfRangeException("count", count, null); return RangeYield(start, end); } private static IEnumerable RangeYield(int start, long end) { for (var i = start; i < end; i++) yield return i; } /// /// Generates a sequence that contains one repeated value. /// public static IEnumerable Repeat(TResult element, int count) { if (count < 0) throw new ArgumentOutOfRangeException("count", count, null); return RepeatYield(element, count); } private static IEnumerable RepeatYield(TResult element, int count) { for (var i = 0; i < count; i++) yield return element; } /// /// Filters a sequence of values based on a predicate. /// public static IEnumerable Where( this IEnumerable source, Func predicate) { if (predicate == null) throw new ArgumentNullException("predicate"); return source.Where((item, i) => predicate(item)); } /// /// Filters a sequence of values based on a predicate. /// Each element's index is used in the logic of the predicate function. /// public static IEnumerable Where( this IEnumerable source, Func predicate) { if (source == null) throw new ArgumentNullException("source"); if (predicate == null) throw new ArgumentNullException("predicate"); return WhereYield(source, predicate); } private static IEnumerable WhereYield( IEnumerable source, Func predicate) { var i = 0; foreach (var item in source) if (predicate(item, i++)) yield return item; } /// /// Projects each element of a sequence into a new form. /// public static IEnumerable Select( this IEnumerable source, Func selector) { if (selector == null) throw new ArgumentNullException("selector"); return source.Select((item, i) => selector(item)); } /// /// Projects each element of a sequence into a new form by /// incorporating the element's index. /// public static IEnumerable Select( this IEnumerable source, Func selector) { if (source == null) throw new ArgumentNullException("source"); if (selector == null) throw new ArgumentNullException("selector"); return SelectYield(source, selector); } private static IEnumerable SelectYield( IEnumerable source, Func selector) { var i = 0; foreach (var item in source) yield return selector(item, i++); } /// /// Projects each element of a sequence to an /// and flattens the resulting sequences into one sequence. /// public static IEnumerable SelectMany( this IEnumerable source, Func> selector) { if (selector == null) throw new ArgumentNullException("selector"); return source.SelectMany((item, i) => selector(item)); } /// /// Projects each element of a sequence to an , /// and flattens the resulting sequences into one sequence. The /// index of each source element is used in the projected form of /// that element. /// public static IEnumerable SelectMany( this IEnumerable source, Func> selector) { if (selector == null) throw new ArgumentNullException("selector"); return source.SelectMany(selector, (item, subitem) => subitem); } /// /// Projects each element of a sequence to an , /// flattens the resulting sequences into one sequence, and invokes /// a result selector function on each element therein. /// public static IEnumerable SelectMany( this IEnumerable source, Func> collectionSelector, Func resultSelector) { if (collectionSelector == null) throw new ArgumentNullException("collectionSelector"); return source.SelectMany((item, i) => collectionSelector(item), resultSelector); } /// /// Projects each element of a sequence to an , /// flattens the resulting sequences into one sequence, and invokes /// a result selector function on each element therein. The index of /// each source element is used in the intermediate projected form /// of that element. /// public static IEnumerable SelectMany( this IEnumerable source, Func> collectionSelector, Func resultSelector) { if (source == null) throw new ArgumentNullException("source"); if (collectionSelector == null) throw new ArgumentNullException("collectionSelector"); if (resultSelector == null) throw new ArgumentNullException("resultSelector"); return SelectManyYield(source, collectionSelector, resultSelector); } private static IEnumerable SelectManyYield( this IEnumerable source, Func> collectionSelector, Func resultSelector) { var i = 0; foreach (var item in source) foreach (var subitem in collectionSelector(item, i++)) yield return resultSelector(item, subitem); } /// /// Returns elements from a sequence as long as a specified condition is true. /// public static IEnumerable TakeWhile( this IEnumerable source, Func predicate) { if (predicate == null) throw new ArgumentNullException("predicate"); return source.TakeWhile((item, i) => predicate(item)); } /// /// Returns elements from a sequence as long as a specified condition is true. /// The element's index is used in the logic of the predicate function. /// public static IEnumerable TakeWhile( this IEnumerable source, Func predicate) { if (source == null) throw new ArgumentNullException("source"); if (predicate == null) throw new ArgumentNullException("predicate"); return TakeWhileYield(source, predicate); } private static IEnumerable TakeWhileYield( this IEnumerable source, Func predicate) { var i = 0; foreach (var item in source) if (predicate(item, i++)) yield return item; else break; } /// /// Returns a specified number of contiguous elements from the start /// of a sequence. /// public static IEnumerable Take( this IEnumerable source, int count) { return source.TakeWhile((item, i) => i < count); } private static class Futures { public static readonly Func Default = () => default(T); public static readonly Func Undefined = () => { throw new InvalidOperationException(); }; } /// /// Base implementation of First operator. /// private static TSource FirstImpl( this IEnumerable source, Func empty) { if (source == null) throw new ArgumentNullException("source"); Debug.Assert(empty != null); var list = source as IList; // optimized case for lists if (list != null) return list.Count > 0 ? list[0] : empty(); using (var e = source.GetEnumerator()) // fallback for enumeration return e.MoveNext() ? e.Current : empty(); } /// /// Returns the first element of a sequence. /// public static TSource First( this IEnumerable source) { return source.FirstImpl(Futures.Undefined); } /// /// Returns the first element in a sequence that satisfies a specified condition. /// public static TSource First( this IEnumerable source, Func predicate) { return First(source.Where(predicate)); } /// /// Returns the first element of a sequence, or a default value if /// the sequence contains no elements. /// public static TSource FirstOrDefault( this IEnumerable source) { return source.FirstImpl(Futures.Default); } /// /// Returns the first element of the sequence that satisfies a /// condition or a default value if no such element is found. /// public static TSource FirstOrDefault( this IEnumerable source, Func predicate) { return FirstOrDefault(source.Where(predicate)); } /// /// Base implementation of Last operator. /// private static TSource LastImpl( this IEnumerable source, Func empty) { if (source == null) throw new ArgumentNullException("source"); var list = source as IList; // optimized case for lists if (list != null) return list.Count > 0 ? list[list.Count - 1] : empty(); using (var e = source.GetEnumerator()) { if (!e.MoveNext()) return empty(); var last = e.Current; while (e.MoveNext()) last = e.Current; return last; } } /// /// Returns the last element of a sequence. /// public static TSource Last( this IEnumerable source) { return source.LastImpl(Futures.Undefined); } /// /// Returns the last element of a sequence that satisfies a /// specified condition. /// public static TSource Last( this IEnumerable source, Func predicate) { return Last(source.Where(predicate)); } /// /// Returns the last element of a sequence, or a default value if /// the sequence contains no elements. /// public static TSource LastOrDefault( this IEnumerable source) { return source.LastImpl(Futures.Default); } /// /// Returns the last element of a sequence that satisfies a /// condition or a default value if no such element is found. /// public static TSource LastOrDefault( this IEnumerable source, Func predicate) { return LastOrDefault(source.Where(predicate)); } /// /// Base implementation of Single operator. /// private static TSource SingleImpl( this IEnumerable source, Func empty) { if (source == null) throw new ArgumentNullException("source"); using (var e = source.GetEnumerator()) { if (e.MoveNext()) { var single = e.Current; if (!e.MoveNext()) return single; throw new InvalidOperationException(); } return empty(); } } /// /// Returns the only element of a sequence, and throws an exception /// if there is not exactly one element in the sequence. /// public static TSource Single( this IEnumerable source) { return source.SingleImpl(Futures.Undefined); } /// /// Returns the only element of a sequence that satisfies a /// specified condition, and throws an exception if more than one /// such element exists. /// public static TSource Single( this IEnumerable source, Func predicate) { return Single(source.Where(predicate)); } /// /// Returns the only element of a sequence, or a default value if /// the sequence is empty; this method throws an exception if there /// is more than one element in the sequence. /// public static TSource SingleOrDefault( this IEnumerable source) { return source.SingleImpl(Futures.Default); } /// /// Returns the only element of a sequence that satisfies a /// specified condition or a default value if no such element /// exists; this method throws an exception if more than one element /// satisfies the condition. /// public static TSource SingleOrDefault( this IEnumerable source, Func predicate) { return SingleOrDefault(source.Where(predicate)); } /// /// Returns the element at a specified index in a sequence. /// public static TSource ElementAt( this IEnumerable source, int index) { if (source == null) throw new ArgumentNullException("source"); if (index < 0) throw new ArgumentOutOfRangeException("index", index, null); var list = source as IList; if (list != null) return list[index]; try { return source.SkipWhile((item, i) => i < index).First(); } catch (InvalidOperationException) // if thrown by First { throw new ArgumentOutOfRangeException("index", index, null); } } /// /// Returns the element at a specified index in a sequence or a /// default value if the index is out of range. /// public static TSource ElementAtOrDefault( this IEnumerable source, int index) { if (source == null) throw new ArgumentNullException("source"); if (index < 0) return default(TSource); var list = source as IList; if (list != null) return index < list.Count ? list[index] : default(TSource); return source.SkipWhile((item, i) => i < index).FirstOrDefault(); } /// /// Inverts the order of the elements in a sequence. /// public static IEnumerable Reverse( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return ReverseYield(source); } private static IEnumerable ReverseYield(IEnumerable source) { var stack = new Stack(); foreach (var item in source) stack.Push(item); foreach (var item in stack) yield return item; } /// /// Bypasses elements in a sequence as long as a specified condition /// is true and then returns the remaining elements. /// public static IEnumerable SkipWhile( this IEnumerable source, Func predicate) { if (predicate == null) throw new ArgumentNullException("predicate"); return source.SkipWhile((item, i) => predicate(item)); } /// /// Bypasses elements in a sequence as long as a specified condition /// is true and then returns the remaining elements. The element's /// index is used in the logic of the predicate function. /// public static IEnumerable SkipWhile( this IEnumerable source, Func predicate) { if (source == null) throw new ArgumentNullException("source"); if (predicate == null) throw new ArgumentNullException("predicate"); return SkipWhileYield(source, predicate); } private static IEnumerable SkipWhileYield( IEnumerable source, Func predicate) { using (var e = source.GetEnumerator()) { for (var i = 0; ; i++) { if (!e.MoveNext()) yield break; if (!predicate(e.Current, i)) break; } do { yield return e.Current; } while (e.MoveNext()); } } /// /// Bypasses a specified number of elements in a sequence and then /// returns the remaining elements. /// public static IEnumerable Skip( this IEnumerable source, int count) { return source.SkipWhile((item, i) => i < count); } /// /// Returns the number of elements in a sequence. /// public static int Count( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); var collection = source as ICollection; return collection != null ? collection.Count : source.Aggregate(0, (count, item) => checked(count + 1)); } /// /// Returns a number that represents how many elements in the /// specified sequence satisfy a condition. /// public static int Count( this IEnumerable source, Func predicate) { return Count(source.Where(predicate)); } /// /// Returns an that represents the total number /// of elements in a sequence. /// public static long LongCount( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); var array = source as Array; return array != null ? array.LongLength : source.Aggregate(0L, (count, item) => count + 1); } /// /// Returns an that represents how many elements /// in a sequence satisfy a condition. /// public static long LongCount( this IEnumerable source, Func predicate) { return LongCount(source.Where(predicate)); } /// /// Concatenates two sequences. /// public static IEnumerable Concat( this IEnumerable first, IEnumerable second) { if (first == null) throw new ArgumentNullException("first"); if (second == null) throw new ArgumentNullException("second"); return ConcatYield(first, second); } private static IEnumerable ConcatYield( IEnumerable first, IEnumerable second) { foreach (var item in first) yield return item; foreach (var item in second) yield return item; } /// /// Creates a from an . /// public static List ToList( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return new List(source); } /// /// Creates an array from an . /// public static TSource[] ToArray( this IEnumerable source) { return source.ToList().ToArray(); } /// /// Returns distinct elements from a sequence by using the default /// equality comparer to compare values. /// public static IEnumerable Distinct( this IEnumerable source) { return Distinct(source, /* comparer */ null); } /// /// Returns distinct elements from a sequence by using a specified /// to compare values. /// public static IEnumerable Distinct( this IEnumerable source, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException("source"); return DistinctYield(source, comparer); } private static IEnumerable DistinctYield( IEnumerable source, IEqualityComparer comparer) { var set = new Dictionary(comparer); var gotNull = false; foreach (var item in source) { if (item == null) { if (gotNull) continue; gotNull = true; } else { if (set.ContainsKey(item)) continue; set.Add(item, null); } yield return item; } } /// /// Creates a from an /// according to a specified key /// selector function. /// public static ILookup ToLookup( this IEnumerable source, Func keySelector) { return ToLookup(source, keySelector, e => e, /* comparer */ null); } /// /// Creates a from an /// according to a specified key /// selector function and a key comparer. /// public static ILookup ToLookup( this IEnumerable source, Func keySelector, IEqualityComparer comparer) { return ToLookup(source, keySelector, e => e, comparer); } /// /// Creates a from an /// according to specified key /// and element selector functions. /// public static ILookup ToLookup( this IEnumerable source, Func keySelector, Func elementSelector) { return ToLookup(source, keySelector, elementSelector, /* comparer */ null); } /// /// Creates a from an /// according to a specified key /// selector function, a comparer and an element selector function. /// public static ILookup ToLookup( this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException("source"); if (keySelector == null) throw new ArgumentNullException("keySelector"); if (elementSelector == null) throw new ArgumentNullException("elementSelector"); var lookup = new Lookup(comparer); foreach (var item in source) { var key = keySelector(item); var grouping = (Grouping)lookup.Find(key); if (grouping == null) { grouping = new Grouping(key); lookup.Add(grouping); } grouping.Add(elementSelector(item)); } return lookup; } /// /// Groups the elements of a sequence according to a specified key /// selector function. /// public static IEnumerable> GroupBy( this IEnumerable source, Func keySelector) { return GroupBy(source, keySelector, /* comparer */ null); } /// /// Groups the elements of a sequence according to a specified key /// selector function and compares the keys by using a specified /// comparer. /// public static IEnumerable> GroupBy( this IEnumerable source, Func keySelector, IEqualityComparer comparer) { return GroupBy(source, keySelector, e => e, comparer); } /// /// Groups the elements of a sequence according to a specified key /// selector function and projects the elements for each group by /// using a specified function. /// public static IEnumerable> GroupBy( this IEnumerable source, Func keySelector, Func elementSelector) { return GroupBy(source, keySelector, elementSelector, /* comparer */ null); } /// /// Groups the elements of a sequence according to a specified key /// selector function and creates a result value from each group and /// its key. /// public static IEnumerable> GroupBy( this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException("source"); if (keySelector == null) throw new ArgumentNullException("keySelector"); if (elementSelector == null) throw new ArgumentNullException("elementSelector"); return ToLookup(source, keySelector, elementSelector, comparer); } /// /// Groups the elements of a sequence according to a key selector /// function. The keys are compared by using a comparer and each /// group's elements are projected by using a specified function. /// public static IEnumerable GroupBy( this IEnumerable source, Func keySelector, Func, TResult> resultSelector) { return GroupBy(source, keySelector, resultSelector, /* comparer */ null); } /// /// Groups the elements of a sequence according to a specified key /// selector function and creates a result value from each group and /// its key. The elements of each group are projected by using a /// specified function. /// public static IEnumerable GroupBy( this IEnumerable source, Func keySelector, Func, TResult> resultSelector, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException("source"); if (keySelector == null) throw new ArgumentNullException("keySelector"); if (resultSelector == null) throw new ArgumentNullException("resultSelector"); return ToLookup(source, keySelector, comparer).Select(g => resultSelector(g.Key, g)); } /// /// Groups the elements of a sequence according to a specified key /// selector function and creates a result value from each group and /// its key. The keys are compared by using a specified comparer. /// public static IEnumerable GroupBy( this IEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector) { return GroupBy(source, keySelector, elementSelector, resultSelector, /* comparer */ null); } /// /// Groups the elements of a sequence according to a specified key /// selector function and creates a result value from each group and /// its key. Key values are compared by using a specified comparer, /// and the elements of each group are projected by using a /// specified function. /// public static IEnumerable GroupBy( this IEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException("source"); if (keySelector == null) throw new ArgumentNullException("keySelector"); if (elementSelector == null) throw new ArgumentNullException("elementSelector"); if (resultSelector == null) throw new ArgumentNullException("resultSelector"); return ToLookup(source, keySelector, elementSelector, comparer) .Select(g => resultSelector(g.Key, g)); } /// /// Applies an accumulator function over a sequence. /// public static TSource Aggregate( this IEnumerable source, Func func) { if (source == null) throw new ArgumentNullException("source"); if (func == null) throw new ArgumentNullException("func"); using (var e = source.GetEnumerator()) { if (!e.MoveNext()) throw new InvalidOperationException(); return e.Renumerable().Skip(1).Aggregate(e.Current, func); } } /// /// Applies an accumulator function over a sequence. The specified /// seed value is used as the initial accumulator value. /// public static TAccumulate Aggregate( this IEnumerable source, TAccumulate seed, Func func) { return Aggregate(source, seed, func, r => r); } /// /// Applies an accumulator function over a sequence. The specified /// seed value is used as the initial accumulator value, and the /// specified function is used to select the result value. /// public static TResult Aggregate( this IEnumerable source, TAccumulate seed, Func func, Func resultSelector) { if (source == null) throw new ArgumentNullException("source"); if (func == null) throw new ArgumentNullException("func"); if (resultSelector == null) throw new ArgumentNullException("resultSelector"); var result = seed; foreach (var item in source) result = func(result, item); return resultSelector(result); } /// /// Produces the set union of two sequences by using the default /// equality comparer. /// public static IEnumerable Union( this IEnumerable first, IEnumerable second) { return Union(first, second, /* comparer */ null); } /// /// Produces the set union of two sequences by using a specified /// . /// public static IEnumerable Union( this IEnumerable first, IEnumerable second, IEqualityComparer comparer) { return first.Concat(second).Distinct(comparer); } /// /// Returns the elements of the specified sequence or the type /// parameter's default value in a singleton collection if the /// sequence is empty. /// public static IEnumerable DefaultIfEmpty( this IEnumerable source) { return source.DefaultIfEmpty(default(TSource)); } /// /// Returns the elements of the specified sequence or the specified /// value in a singleton collection if the sequence is empty. /// public static IEnumerable DefaultIfEmpty( this IEnumerable source, TSource defaultValue) { if (source == null) throw new ArgumentNullException("source"); return DefaultIfEmptyYield(source, defaultValue); } private static IEnumerable DefaultIfEmptyYield( IEnumerable source, TSource defaultValue) { using (var e = source.GetEnumerator()) { if (!e.MoveNext()) yield return defaultValue; else do { yield return e.Current; } while (e.MoveNext()); } } /// /// Determines whether all elements of a sequence satisfy a condition. /// public static bool All( this IEnumerable source, Func predicate) { if (source == null) throw new ArgumentNullException("source"); if (predicate == null) throw new ArgumentNullException("predicate"); foreach (var item in source) if (!predicate(item)) return false; return true; } /// /// Determines whether a sequence contains any elements. /// public static bool Any( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); using (var e = source.GetEnumerator()) return e.MoveNext(); } /// /// Determines whether any element of a sequence satisfies a /// condition. /// public static bool Any( this IEnumerable source, Func predicate) { return source.Where(predicate).Any(); } /// /// Determines whether a sequence contains a specified element by /// using the default equality comparer. /// public static bool Contains( this IEnumerable source, TSource value) { return source.Contains(value, /* comparer */ null); } /// /// Determines whether a sequence contains a specified element by /// using a specified . /// public static bool Contains( this IEnumerable source, TSource value, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException("source"); if (comparer == null) { var collection = source as ICollection; if (collection != null) return collection.Contains(value); } comparer = comparer ?? EqualityComparer.Default; return source.Any(item => comparer.Equals(item, value)); } /// /// Determines whether two sequences are equal by comparing the /// elements by using the default equality comparer for their type. /// public static bool SequenceEqual( this IEnumerable first, IEnumerable second) { return first.SequenceEqual(second, /* comparer */ null); } /// /// Determines whether two sequences are equal by comparing their /// elements by using a specified . /// public static bool SequenceEqual( this IEnumerable first, IEnumerable second, IEqualityComparer comparer) { if (first == null) throw new ArgumentNullException("frist"); if (second == null) throw new ArgumentNullException("second"); comparer = comparer ?? EqualityComparer.Default; using (IEnumerator lhs = first.GetEnumerator(), rhs = second.GetEnumerator()) { do { if (!lhs.MoveNext()) return !rhs.MoveNext(); if (!rhs.MoveNext()) return false; } while (comparer.Equals(lhs.Current, rhs.Current)); } return false; } /// /// Base implementation for Min/Max operator. /// private static TSource MinMaxImpl( this IEnumerable source, Func lesser) { if (source == null) throw new ArgumentNullException("source"); Debug.Assert(lesser != null); if (typeof(TSource).IsClass) // ReSharper disable CompareNonConstrainedGenericWithNull source = source.Where(e => e != null).DefaultIfEmpty(); // ReSharper restore CompareNonConstrainedGenericWithNull return source.Aggregate((a, item) => lesser(a, item) ? a : item); } /// /// Base implementation for Min/Max operator for nullable types. /// private static TSource? MinMaxImpl( this IEnumerable source, TSource? seed, Func lesser) where TSource : struct { if (source == null) throw new ArgumentNullException("source"); Debug.Assert(lesser != null); return source.Aggregate(seed, (a, item) => lesser(a, item) ? a : item); // == MinMaxImpl(Repeat(null, 1).Concat(source), lesser); } /// /// Returns the minimum value in a generic sequence. /// public static TSource Min( this IEnumerable source) { var comparer = Comparer.Default; return source.MinMaxImpl((x, y) => comparer.Compare(x, y) < 0); } /// /// Invokes a transform function on each element of a generic /// sequence and returns the minimum resulting value. /// public static TResult Min( this IEnumerable source, Func selector) { return source.Select(selector).Min(); } /// /// Returns the maximum value in a generic sequence. /// public static TSource Max( this IEnumerable source) { var comparer = Comparer.Default; return source.MinMaxImpl((x, y) => comparer.Compare(x, y) > 0); } /// /// Invokes a transform function on each element of a generic /// sequence and returns the maximum resulting value. /// public static TResult Max( this IEnumerable source, Func selector) { return source.Select(selector).Max(); } /// /// Makes an enumerator seen as enumerable once more. /// /// /// The supplied enumerator must have been started. The first element /// returned is the element the enumerator was on when passed in. /// DO NOT use this method if the caller must be a generator. It is /// mostly safe among aggregate operations. /// private static IEnumerable Renumerable(this IEnumerator e) { Debug.Assert(e != null); do { yield return e.Current; } while (e.MoveNext()); } /// /// Sorts the elements of a sequence in ascending order according to a key. /// public static IOrderedEnumerable OrderBy( this IEnumerable source, Func keySelector) { return source.OrderBy(keySelector, /* comparer */ null); } /// /// Sorts the elements of a sequence in ascending order by using a /// specified comparer. /// public static IOrderedEnumerable OrderBy( this IEnumerable source, Func keySelector, IComparer comparer) { if (source == null) throw new ArgumentNullException("source"); if (keySelector == null) throw new ArgumentNullException("keySelector"); return new OrderedEnumerable(source, keySelector, comparer, /* descending */ false); } /// /// Sorts the elements of a sequence in descending order according to a key. /// public static IOrderedEnumerable OrderByDescending( this IEnumerable source, Func keySelector) { return source.OrderByDescending(keySelector, /* comparer */ null); } /// /// Sorts the elements of a sequence in descending order by using a /// specified comparer. /// public static IOrderedEnumerable OrderByDescending( this IEnumerable source, Func keySelector, IComparer comparer) { if (source == null) throw new ArgumentNullException("source"); if (source == null) throw new ArgumentNullException("keySelector"); return new OrderedEnumerable(source, keySelector, comparer, /* descending */ true); } /// /// Performs a subsequent ordering of the elements in a sequence in /// ascending order according to a key. /// public static IOrderedEnumerable ThenBy( this IOrderedEnumerable source, Func keySelector) { return source.ThenBy(keySelector, /* comparer */ null); } /// /// Performs a subsequent ordering of the elements in a sequence in /// ascending order by using a specified comparer. /// public static IOrderedEnumerable ThenBy( this IOrderedEnumerable source, Func keySelector, IComparer comparer) { if (source == null) throw new ArgumentNullException("source"); return source.CreateOrderedEnumerable(keySelector, comparer, /* descending */ false); } /// /// Performs a subsequent ordering of the elements in a sequence in /// descending order, according to a key. /// public static IOrderedEnumerable ThenByDescending( this IOrderedEnumerable source, Func keySelector) { return source.ThenByDescending(keySelector, /* comparer */ null); } /// /// Performs a subsequent ordering of the elements in a sequence in /// descending order by using a specified comparer. /// public static IOrderedEnumerable ThenByDescending( this IOrderedEnumerable source, Func keySelector, IComparer comparer) { if (source == null) throw new ArgumentNullException("source"); return source.CreateOrderedEnumerable(keySelector, comparer, /* descending */ true); } /// /// Base implementation for Intersect and Except operators. /// private static IEnumerable IntersectExceptImpl( this IEnumerable first, IEnumerable second, IEqualityComparer comparer, bool flag) { if (first == null) throw new ArgumentNullException("first"); if (second == null) throw new ArgumentNullException("second"); var keys = new List>(); var flags = new Dictionary, bool>(new KeyComparer(comparer)); foreach (var item in from item in first select new Key(item) into item where !flags.ContainsKey(item) select item) { flags.Add(item, !flag); keys.Add(item); } foreach (var item in from item in second select new Key(item) into item where flags.ContainsKey(item) select item) { flags[item] = flag; } // // As per docs, "the marked elements are yielded in the order in // which they were collected. // return from item in keys where flags[item] select item.Value; } /// /// Produces the set intersection of two sequences by using the /// default equality comparer to compare values. /// public static IEnumerable Intersect( this IEnumerable first, IEnumerable second) { return first.Intersect(second, /* comparer */ null); } /// /// Produces the set intersection of two sequences by using the /// specified to compare values. /// public static IEnumerable Intersect( this IEnumerable first, IEnumerable second, IEqualityComparer comparer) { return IntersectExceptImpl(first, second, comparer, /* flag */ true); } /// /// Produces the set difference of two sequences by using the /// default equality comparer to compare values. /// public static IEnumerable Except( this IEnumerable first, IEnumerable second) { return first.Except(second, /* comparer */ null); } /// /// Produces the set difference of two sequences by using the /// specified to compare values. /// public static IEnumerable Except( this IEnumerable first, IEnumerable second, IEqualityComparer comparer) { return IntersectExceptImpl(first, second, comparer, /* flag */ false); } /// /// Creates a from an /// according to a specified key /// selector function. /// public static Dictionary ToDictionary( this IEnumerable source, Func keySelector) { return source.ToDictionary(keySelector, /* comparer */ null); } /// /// Creates a from an /// according to a specified key /// selector function and key comparer. /// public static Dictionary ToDictionary( this IEnumerable source, Func keySelector, IEqualityComparer comparer) { return source.ToDictionary(keySelector, e => e, comparer); } /// /// Creates a from an /// according to specified key /// selector and element selector functions. /// public static Dictionary ToDictionary( this IEnumerable source, Func keySelector, Func elementSelector) { return source.ToDictionary(keySelector, elementSelector, /* comparer */ null); } /// /// Creates a from an /// according to a specified key /// selector function, a comparer, and an element selector function. /// public static Dictionary ToDictionary( this IEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException("source"); if (keySelector == null) throw new ArgumentNullException("keySelector"); if (elementSelector == null) throw new ArgumentNullException("elementSelector"); var dict = new Dictionary(comparer); foreach (var item in source) { // // ToDictionary is meant to throw ArgumentNullException if // keySelector produces a key that is null and // Argument exception if keySelector produces duplicate keys // for two elements. Incidentally, the doucmentation for // IDictionary.Add says that the Add method // throws the same exceptions under the same circumstances // so we don't need to do any additional checking or work // here and let the Add implementation do all the heavy // lifting. // dict.Add(keySelector(item), elementSelector(item)); } return dict; } /// /// Correlates the elements of two sequences based on matching keys. /// The default equality comparer is used to compare keys. /// public static IEnumerable Join( this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector) { return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, /* comparer */ null); } /// /// Correlates the elements of two sequences based on matching keys. /// The default equality comparer is used to compare keys. A /// specified is used to compare keys. /// public static IEnumerable Join( this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector, IEqualityComparer comparer) { if (outer == null) throw new ArgumentNullException("outer"); if (inner == null) throw new ArgumentNullException("inner"); if (outerKeySelector == null) throw new ArgumentNullException("outerKeySelector"); if (innerKeySelector == null) throw new ArgumentNullException("innerKeySelector"); if (resultSelector == null) throw new ArgumentNullException("resultSelector"); var lookup = inner.ToLookup(innerKeySelector, comparer); return from o in outer from i in lookup[outerKeySelector(o)] select resultSelector(o, i); } /// /// Correlates the elements of two sequences based on equality of /// keys and groups the results. The default equality comparer is /// used to compare keys. /// public static IEnumerable GroupJoin( this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector) { return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, /* comparer */ null); } /// /// Correlates the elements of two sequences based on equality of /// keys and groups the results. The default equality comparer is /// used to compare keys. A specified /// is used to compare keys. /// public static IEnumerable GroupJoin( this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector, IEqualityComparer comparer) { if (outer == null) throw new ArgumentNullException("outer"); if (inner == null) throw new ArgumentNullException("inner"); if (outerKeySelector == null) throw new ArgumentNullException("outerKeySelector"); if (innerKeySelector == null) throw new ArgumentNullException("innerKeySelector"); if (resultSelector == null) throw new ArgumentNullException("resultSelector"); var lookup = inner.ToLookup(innerKeySelector, comparer); return outer.Select(o => resultSelector(o, lookup[outerKeySelector(o)])); } private static class Sequence { public static readonly IEnumerable Empty = new T[0]; } private sealed class Grouping : List, IGrouping { internal Grouping(K key) { Key = key; } public K Key { get; private set; } } } } // $Id: Enumerable.g.tt 71137f497bf2 2012/04/16 20:01:27 azizatif $ namespace System.Linq { #region Imports using System; using System.Collections.Generic; #endregion // This partial implementation was template-generated: // Mon, 16 Apr 2012 20:05:53 GMT partial class Enumerable { /// /// Computes the sum of a sequence of nullable values. /// public static int Sum( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); int sum = 0; foreach (var num in source) sum = checked(sum + num); return sum; } /// /// Computes the sum of a sequence of nullable /// values that are obtained by invoking a transform function on /// each element of the input sequence. /// public static int Sum( this IEnumerable source, Func selector) { return source.Select(selector).Sum(); } /// /// Computes the average of a sequence of nullable values. /// public static double Average( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); long sum = 0; long count = 0; foreach (var num in source) checked { sum += (int)num; count++; } if (count == 0) throw new InvalidOperationException(); return (double)sum / count; } /// /// Computes the average of a sequence of nullable values /// that are obtained by invoking a transform function on each /// element of the input sequence. /// public static double Average( this IEnumerable source, Func selector) { return source.Select(selector).Average(); } /// /// Computes the sum of a sequence of values. /// public static int? Sum( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); int sum = 0; foreach (var num in source) sum = checked(sum + (num ?? 0)); return sum; } /// /// Computes the sum of a sequence of /// values that are obtained by invoking a transform function on /// each element of the input sequence. /// public static int? Sum( this IEnumerable source, Func selector) { return source.Select(selector).Sum(); } /// /// Computes the average of a sequence of values. /// public static double? Average( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); long sum = 0; long count = 0; foreach (var num in source.Where(n => n != null)) checked { sum += (int)num; count++; } if (count == 0) return null; return (double?)sum / count; } /// /// Computes the average of a sequence of values /// that are obtained by invoking a transform function on each /// element of the input sequence. /// public static double? Average( this IEnumerable source, Func selector) { return source.Select(selector).Average(); } /// /// Returns the minimum value in a sequence of nullable /// values. /// public static int? Min( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); } /// /// Invokes a transform function on each element of a sequence and /// returns the minimum nullable value. /// public static int? Min( this IEnumerable source, Func selector) { return source.Select(selector).Min(); } /// /// Returns the maximum value in a sequence of nullable /// values. /// public static int? Max( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return MinMaxImpl(source.Where(x => x != null), null, (max, x) => x == null || (max != null && x.Value < max.Value)); } /// /// Invokes a transform function on each element of a sequence and /// returns the maximum nullable value. /// public static int? Max( this IEnumerable source, Func selector) { return source.Select(selector).Max(); } /// /// Computes the sum of a sequence of nullable values. /// public static long Sum( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); long sum = 0; foreach (var num in source) sum = checked(sum + num); return sum; } /// /// Computes the sum of a sequence of nullable /// values that are obtained by invoking a transform function on /// each element of the input sequence. /// public static long Sum( this IEnumerable source, Func selector) { return source.Select(selector).Sum(); } /// /// Computes the average of a sequence of nullable values. /// public static double Average( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); long sum = 0; long count = 0; foreach (var num in source) checked { sum += (long)num; count++; } if (count == 0) throw new InvalidOperationException(); return (double)sum / count; } /// /// Computes the average of a sequence of nullable values /// that are obtained by invoking a transform function on each /// element of the input sequence. /// public static double Average( this IEnumerable source, Func selector) { return source.Select(selector).Average(); } /// /// Computes the sum of a sequence of values. /// public static long? Sum( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); long sum = 0; foreach (var num in source) sum = checked(sum + (num ?? 0)); return sum; } /// /// Computes the sum of a sequence of /// values that are obtained by invoking a transform function on /// each element of the input sequence. /// public static long? Sum( this IEnumerable source, Func selector) { return source.Select(selector).Sum(); } /// /// Computes the average of a sequence of values. /// public static double? Average( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); long sum = 0; long count = 0; foreach (var num in source.Where(n => n != null)) checked { sum += (long)num; count++; } if (count == 0) return null; return (double?)sum / count; } /// /// Computes the average of a sequence of values /// that are obtained by invoking a transform function on each /// element of the input sequence. /// public static double? Average( this IEnumerable source, Func selector) { return source.Select(selector).Average(); } /// /// Returns the minimum value in a sequence of nullable /// values. /// public static long? Min( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); } /// /// Invokes a transform function on each element of a sequence and /// returns the minimum nullable value. /// public static long? Min( this IEnumerable source, Func selector) { return source.Select(selector).Min(); } /// /// Returns the maximum value in a sequence of nullable /// values. /// public static long? Max( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return MinMaxImpl(source.Where(x => x != null), null, (max, x) => x == null || (max != null && x.Value < max.Value)); } /// /// Invokes a transform function on each element of a sequence and /// returns the maximum nullable value. /// public static long? Max( this IEnumerable source, Func selector) { return source.Select(selector).Max(); } /// /// Computes the sum of a sequence of nullable values. /// public static float Sum( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); float sum = 0; foreach (var num in source) sum = checked(sum + num); return sum; } /// /// Computes the sum of a sequence of nullable /// values that are obtained by invoking a transform function on /// each element of the input sequence. /// public static float Sum( this IEnumerable source, Func selector) { return source.Select(selector).Sum(); } /// /// Computes the average of a sequence of nullable values. /// public static float Average( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); float sum = 0; long count = 0; foreach (var num in source) checked { sum += (float)num; count++; } if (count == 0) throw new InvalidOperationException(); return (float)sum / count; } /// /// Computes the average of a sequence of nullable values /// that are obtained by invoking a transform function on each /// element of the input sequence. /// public static float Average( this IEnumerable source, Func selector) { return source.Select(selector).Average(); } /// /// Computes the sum of a sequence of values. /// public static float? Sum( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); float sum = 0; foreach (var num in source) sum = checked(sum + (num ?? 0)); return sum; } /// /// Computes the sum of a sequence of /// values that are obtained by invoking a transform function on /// each element of the input sequence. /// public static float? Sum( this IEnumerable source, Func selector) { return source.Select(selector).Sum(); } /// /// Computes the average of a sequence of values. /// public static float? Average( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); float sum = 0; long count = 0; foreach (var num in source.Where(n => n != null)) checked { sum += (float)num; count++; } if (count == 0) return null; return (float?)sum / count; } /// /// Computes the average of a sequence of values /// that are obtained by invoking a transform function on each /// element of the input sequence. /// public static float? Average( this IEnumerable source, Func selector) { return source.Select(selector).Average(); } /// /// Returns the minimum value in a sequence of nullable /// values. /// public static float? Min( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); } /// /// Invokes a transform function on each element of a sequence and /// returns the minimum nullable value. /// public static float? Min( this IEnumerable source, Func selector) { return source.Select(selector).Min(); } /// /// Returns the maximum value in a sequence of nullable /// values. /// public static float? Max( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return MinMaxImpl(source.Where(x => x != null), null, (max, x) => x == null || (max != null && x.Value < max.Value)); } /// /// Invokes a transform function on each element of a sequence and /// returns the maximum nullable value. /// public static float? Max( this IEnumerable source, Func selector) { return source.Select(selector).Max(); } /// /// Computes the sum of a sequence of nullable values. /// public static double Sum( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); double sum = 0; foreach (var num in source) sum = checked(sum + num); return sum; } /// /// Computes the sum of a sequence of nullable /// values that are obtained by invoking a transform function on /// each element of the input sequence. /// public static double Sum( this IEnumerable source, Func selector) { return source.Select(selector).Sum(); } /// /// Computes the average of a sequence of nullable values. /// public static double Average( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); double sum = 0; long count = 0; foreach (var num in source) checked { sum += (double)num; count++; } if (count == 0) throw new InvalidOperationException(); return (double)sum / count; } /// /// Computes the average of a sequence of nullable values /// that are obtained by invoking a transform function on each /// element of the input sequence. /// public static double Average( this IEnumerable source, Func selector) { return source.Select(selector).Average(); } /// /// Computes the sum of a sequence of values. /// public static double? Sum( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); double sum = 0; foreach (var num in source) sum = checked(sum + (num ?? 0)); return sum; } /// /// Computes the sum of a sequence of /// values that are obtained by invoking a transform function on /// each element of the input sequence. /// public static double? Sum( this IEnumerable source, Func selector) { return source.Select(selector).Sum(); } /// /// Computes the average of a sequence of values. /// public static double? Average( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); double sum = 0; long count = 0; foreach (var num in source.Where(n => n != null)) checked { sum += (double)num; count++; } if (count == 0) return null; return (double?)sum / count; } /// /// Computes the average of a sequence of values /// that are obtained by invoking a transform function on each /// element of the input sequence. /// public static double? Average( this IEnumerable source, Func selector) { return source.Select(selector).Average(); } /// /// Returns the minimum value in a sequence of nullable /// values. /// public static double? Min( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); } /// /// Invokes a transform function on each element of a sequence and /// returns the minimum nullable value. /// public static double? Min( this IEnumerable source, Func selector) { return source.Select(selector).Min(); } /// /// Returns the maximum value in a sequence of nullable /// values. /// public static double? Max( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return MinMaxImpl(source.Where(x => x != null), null, (max, x) => x == null || (max != null && x.Value < max.Value)); } /// /// Invokes a transform function on each element of a sequence and /// returns the maximum nullable value. /// public static double? Max( this IEnumerable source, Func selector) { return source.Select(selector).Max(); } /// /// Computes the sum of a sequence of nullable values. /// public static decimal Sum( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); decimal sum = 0; foreach (var num in source) sum = checked(sum + num); return sum; } /// /// Computes the sum of a sequence of nullable /// values that are obtained by invoking a transform function on /// each element of the input sequence. /// public static decimal Sum( this IEnumerable source, Func selector) { return source.Select(selector).Sum(); } /// /// Computes the average of a sequence of nullable values. /// public static decimal Average( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); decimal sum = 0; long count = 0; foreach (var num in source) checked { sum += (decimal)num; count++; } if (count == 0) throw new InvalidOperationException(); return (decimal)sum / count; } /// /// Computes the average of a sequence of nullable values /// that are obtained by invoking a transform function on each /// element of the input sequence. /// public static decimal Average( this IEnumerable source, Func selector) { return source.Select(selector).Average(); } /// /// Computes the sum of a sequence of values. /// public static decimal? Sum( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); decimal sum = 0; foreach (var num in source) sum = checked(sum + (num ?? 0)); return sum; } /// /// Computes the sum of a sequence of /// values that are obtained by invoking a transform function on /// each element of the input sequence. /// public static decimal? Sum( this IEnumerable source, Func selector) { return source.Select(selector).Sum(); } /// /// Computes the average of a sequence of values. /// public static decimal? Average( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); decimal sum = 0; long count = 0; foreach (var num in source.Where(n => n != null)) checked { sum += (decimal)num; count++; } if (count == 0) return null; return (decimal?)sum / count; } /// /// Computes the average of a sequence of values /// that are obtained by invoking a transform function on each /// element of the input sequence. /// public static decimal? Average( this IEnumerable source, Func selector) { return source.Select(selector).Average(); } /// /// Returns the minimum value in a sequence of nullable /// values. /// public static decimal? Min( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); } /// /// Invokes a transform function on each element of a sequence and /// returns the minimum nullable value. /// public static decimal? Min( this IEnumerable source, Func selector) { return source.Select(selector).Min(); } /// /// Returns the maximum value in a sequence of nullable /// values. /// public static decimal? Max( this IEnumerable source) { if (source == null) throw new ArgumentNullException("source"); return MinMaxImpl(source.Where(x => x != null), null, (max, x) => x == null || (max != null && x.Value < max.Value)); } /// /// Invokes a transform function on each element of a sequence and /// returns the maximum nullable value. /// public static decimal? Max( this IEnumerable source, Func selector) { return source.Select(selector).Max(); } } } // $Id: Func.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ namespace System { #if LINQBRIDGE_LIB public delegate TResult Func(); public delegate TResult Func(T a); public delegate TResult Func(T1 arg1, T2 arg2); public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); #else delegate TResult Func(); delegate TResult Func(T a); delegate TResult Func(T1 arg1, T2 arg2); delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); #endif } // $Id: IGrouping.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ namespace System.Linq { #region Imports using System.Collections.Generic; #endregion /// /// Represents a collection of objects that have a common key. /// partial interface IGrouping : IEnumerable { /// /// Gets the key of the . /// TKey Key { get; } } } // $Id: ILookup.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ namespace System.Linq { using System.Collections.Generic; /// /// Defines an indexer, size property, and Boolean search method for /// data structures that map keys to /// sequences of values. /// partial interface ILookup : IEnumerable> { bool Contains(TKey key); int Count { get; } IEnumerable this[TKey key] { get; } } } // $Id: Internal.cs 1567e00f1a20 2012/04/17 16:09:51 azizatif $ namespace LinqBridge { #region Imports using System; using System.Collections.Generic; #endregion /// /// This type is not intended to be used directly from user code. /// It may be removed or changed in a future version without notice. /// sealed class DelegatingComparer : IComparer { private readonly Func _comparer; public DelegatingComparer(Func comparer) { if (comparer == null) throw new ArgumentNullException("comparer"); _comparer = comparer; } public int Compare(T x, T y) { return _comparer(x, y); } } /// /// This type is not intended to be used directly from user code. /// It may be removed or changed in a future version without notice. /// struct Key { public Key(T value) : this() { Value = value; } public T Value { get; private set; } } /// /// This type is not intended to be used directly from user code. /// It may be removed or changed in a future version without notice. /// sealed class KeyComparer : IEqualityComparer> { private readonly IEqualityComparer _innerComparer; public KeyComparer(IEqualityComparer innerComparer) { _innerComparer = innerComparer ?? EqualityComparer.Default; } public bool Equals(Key x, Key y) { return _innerComparer.Equals(x.Value, y.Value); } public int GetHashCode(Key obj) { return obj.Value == null ? 0 : _innerComparer.GetHashCode(obj.Value); } } } // $Id: IOrderedEnumerable.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ namespace System.Linq { using System.Collections.Generic; /// /// Represents a sorted sequence. /// partial interface IOrderedEnumerable : IEnumerable { /// /// Performs a subsequent ordering on the elements of an /// according to a key. /// IOrderedEnumerable CreateOrderedEnumerable( Func keySelector, IComparer comparer, bool descending); } } // $Id: Lookup.cs c08984d432b1 2012/04/17 16:05:19 azizatif $ namespace System.Linq { #region Imports using System; using System.Collections; using System.Collections.Generic; using IEnumerable = System.Collections.IEnumerable; using LinqBridge; #endregion /// /// Represents a collection of keys each mapped to one or more values. /// internal sealed class Lookup : ILookup { private readonly Dictionary, IGrouping> _map; private readonly List> _orderedKeys; // remember order of insertion internal Lookup(IEqualityComparer comparer) { _map = new Dictionary, IGrouping>(new KeyComparer(comparer)); _orderedKeys = new List>(); } internal void Add(IGrouping item) { var key = new Key(item.Key); _map.Add(key, item); _orderedKeys.Add(key); } internal IEnumerable Find(TKey key) { IGrouping grouping; return _map.TryGetValue(new Key(key), out grouping) ? grouping : null; } /// /// Gets the number of key/value collection pairs in the . /// public int Count { get { return _map.Count; } } /// /// Gets the collection of values indexed by the specified key. /// public IEnumerable this[TKey key] { get { IGrouping result; return _map.TryGetValue(new Key(key), out result) ? result : Enumerable.Empty(); } } /// /// Determines whether a specified key is in the . /// public bool Contains(TKey key) { return _map.ContainsKey(new Key(key)); } /// /// Applies a transform function to each key and its associated /// values and returns the results. /// public IEnumerable ApplyResultSelector( Func, TResult> resultSelector) { if (resultSelector == null) throw new ArgumentNullException("resultSelector"); foreach (var pair in _map) yield return resultSelector(pair.Key.Value, pair.Value); } /// /// Returns a generic enumerator that iterates through the . /// public IEnumerator> GetEnumerator() { foreach (var key in _orderedKeys) yield return _map[key]; } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } } // $Id: OrderedEnumerable.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ namespace LinqBridge { #region Imports using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; #endregion internal sealed class OrderedEnumerable : IOrderedEnumerable { private readonly IEnumerable _source; private readonly Func, IComparer> _comparerComposer; public OrderedEnumerable(IEnumerable source, Func keySelector, IComparer comparer, bool descending) : this(source, (_, next) => next, keySelector, comparer, descending) { } private OrderedEnumerable(IEnumerable source, Func, IComparer> parent, Func keySelector, IComparer comparer, bool descending) { if (source == null) throw new ArgumentNullException("source"); if (keySelector == null) throw new ArgumentNullException("keySelector"); Debug.Assert(parent != null); _source = source; comparer = comparer ?? Comparer.Default; var direction = descending ? -1 : 1; _comparerComposer = (items, next) => { Debug.Assert(items != null); Debug.Assert(next != null); var keys = new K[items.Length]; for (var i = 0; i < items.Length; i++) keys[i] = keySelector(items[i]); return parent(items, new DelegatingComparer((i, j) => { var result = direction * comparer.Compare(keys[i], keys[j]); return result != 0 ? result : next.Compare(i, j); })); }; } public IOrderedEnumerable CreateOrderedEnumerable( Func keySelector, IComparer comparer, bool descending) { return new OrderedEnumerable(_source, _comparerComposer, keySelector, comparer, descending); } public IEnumerator GetEnumerator() { // // Sort using Array.Sort but docs say that it performs an // unstable sort. LINQ, on the other hand, says OrderBy performs // a stable sort. Use the item position then as a tie // breaker when all keys compare equal, thus making the sort // stable. // var items = _source.ToArray(); var positionComparer = new DelegatingComparer((i, j) => i.CompareTo(j)); var comparer = _comparerComposer(items, positionComparer); var keys = new int[items.Length]; for (var i = 0; i < keys.Length; i++) keys[i] = i; Array.Sort(keys, items, comparer); return ((IEnumerable)items).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } } // $Id: Action.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ namespace System { #if LINQBRIDGE_LIB public delegate void Action(); public delegate void Action(T1 arg1, T2 arg2); public delegate void Action(T1 arg1, T2 arg2, T3 arg3); public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); #else delegate void Action(); delegate void Action(T1 arg1, T2 arg2); delegate void Action(T1 arg1, T2 arg2, T3 arg3); delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); #endif } #endif #endregion