2009-02-13 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.Core / System.Linq / Enumerable.cs
1 //
2 // Enumerable.cs
3 //
4 // Authors:
5 //  Marek Safar (marek.safar@gmail.com)
6 //  Antonello Provenzano  <antonello@deveel.com>
7 //  Alejandro Serrano "Serras" (trupill@yahoo.es)
8 //  Jb Evain (jbevain@novell.com)
9 //
10 // Copyright (C) 2007 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 // precious: http://www.hookedonlinq.com
33
34 using System;
35 using System.Collections;
36 using System.Collections.Generic;
37 using System.Collections.ObjectModel;
38
39 namespace System.Linq
40 {
41         public static class Enumerable
42         {
43                 enum Fallback {
44                         Default,
45                         Throw
46                 }
47
48                 class PredicateOf<T> {
49                         public static readonly Func<T, bool> Always = (t) => true;
50                 }
51
52                 class Function<T> {
53                         public static readonly Func<T, T> Identity = (t) => t;
54                 }
55
56                 #region Aggregate
57
58                 public static TSource Aggregate<TSource> (this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func)
59                 {
60                         Check.SourceAndFunc (source, func);
61
62                         // custom foreach so that we can efficiently throw an exception
63                         // if zero elements and treat the first element differently
64                         using (var enumerator = source.GetEnumerator ()) {
65                                 if (!enumerator.MoveNext ())
66                                         throw new InvalidOperationException ("No elements in source list");
67
68                                 TSource folded = enumerator.Current;
69                                 while (enumerator.MoveNext ())
70                                         folded = func (folded, enumerator.Current);
71                                 return folded;
72                         }
73                 }
74
75                 public static TAccumulate Aggregate<TSource, TAccumulate> (this IEnumerable<TSource> source,
76                         TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func)
77                 {
78                         Check.SourceAndFunc (source, func);
79
80                         TAccumulate folded = seed;
81                         foreach (TSource element in source)
82                                 folded = func (folded, element);
83
84                         return folded;
85                 }
86
87                 public static TResult Aggregate<TSource, TAccumulate, TResult> (this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector)
88                 {
89                         Check.SourceAndFunc (source, func);
90                         if (resultSelector == null)
91                                 throw new ArgumentNullException ("resultSelector");
92
93                         var result = seed;
94                         foreach (var e in source)
95                                 result = func (result, e);
96
97                         return resultSelector (result);
98                 }
99
100                 #endregion
101
102                 #region All
103
104                 public static bool All<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
105                 {
106                         Check.SourceAndPredicate (source, predicate);
107
108                         foreach (var element in source)
109                                 if (!predicate (element))
110                                         return false;
111
112                         return true;
113                 }
114
115                 #endregion
116
117                 #region Any
118
119                 public static bool Any<TSource> (this IEnumerable<TSource> source)
120                 {
121                         Check.Source (source);
122
123                         var collection = source as ICollection<TSource>;
124                         if (collection != null)
125                                 return collection.Count > 0;
126
127                         using (var enumerator = source.GetEnumerator ())
128                                 return enumerator.MoveNext ();
129                 }
130
131                 public static bool Any<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
132                 {
133                         Check.SourceAndPredicate (source, predicate);
134
135                         foreach (TSource element in source)
136                                 if (predicate (element))
137                                         return true;
138
139                         return false;
140                 }
141
142                 #endregion
143
144                 #region AsEnumerable
145
146                 public static IEnumerable<TSource> AsEnumerable<TSource> (this IEnumerable<TSource> source)
147                 {
148                         return source;
149                 }
150
151                 #endregion
152
153                 #region Average
154
155                 public static double Average (this IEnumerable<int> source)
156                 {
157                         return Average<int, long, double> (source, (a, b) => a + b, (a, b) => (double) a / (double) b);
158                 }
159
160                 public static double Average (this IEnumerable<long> source)
161                 {
162                         return Average<long, long, double> (source, (a, b) => a + b, (a, b) => (double) a / (double) b);
163                 }
164
165                 public static double Average (this IEnumerable<double> source)
166                 {
167                         return Average<double, double, double> (source, (a, b) => a + b, (a, b) => a / b);
168                 }
169
170                 public static float Average (this IEnumerable<float> source)
171                 {
172                         return Average<float, double, float> (source, (a, b) => a + b, (a, b) => (float) a / (float) b);
173                 }
174
175                 public static decimal Average (this IEnumerable<decimal> source)
176                 {
177                         return Average<decimal, decimal, decimal> (source, (a, b) => a + b, (a, b) => a / b);
178                 }
179
180                 static TResult Average<TElement, TAggregate, TResult> (this IEnumerable<TElement> source,
181                         Func<TAggregate, TElement, TAggregate> func, Func<TAggregate, long, TResult> result)
182                         where TElement : struct
183                         where TAggregate : struct
184                         where TResult : struct
185                 {
186                         Check.Source (source);
187
188                         var total = default (TAggregate);
189                         long counter = 0;
190                         foreach (var element in source) {
191                                 total = func (total, element);
192                                 ++counter;
193                         }
194
195                         if (counter == 0)
196                                 throw new InvalidOperationException ();
197
198                         return result (total, counter);
199                 }
200
201                 static TResult? AverageNullable<TElement, TAggregate, TResult> (this IEnumerable<TElement?> source,
202                         Func<TAggregate, TElement, TAggregate> func, Func<TAggregate, long, TResult> result)
203                         where TElement : struct
204                         where TAggregate : struct
205                         where TResult : struct
206                 {
207                         Check.Source (source);
208
209                         var total = default (TAggregate);
210                         long counter = 0;
211                         foreach (var element in source) {
212                                 if (!element.HasValue)
213                                         continue;
214
215                                 total = func (total, element.Value);
216                                 counter++;
217                         }
218
219                         if (counter == 0)
220                                 return null;
221
222                         return new TResult? (result (total, counter));
223                 }
224
225                 public static double? Average (this IEnumerable<int?> source)
226                 {
227                         Check.Source (source);
228
229                         return source.AverageNullable<int, long, double> ((a, b) => a + b, (a, b) => (double) a / (double) b);
230                 }
231
232                 public static double? Average (this IEnumerable<long?> source)
233                 {
234                         Check.Source (source);
235
236                         return source.AverageNullable<long, long, double> ((a, b) => a + b, (a, b) => (double) a / b);
237                 }
238
239                 public static double? Average (this IEnumerable<double?> source)
240                 {
241                         Check.Source (source);
242
243                         return source.AverageNullable<double, double, double> ((a, b) => a + b, (a, b) => a / b);
244                 }
245
246                 public static decimal? Average (this IEnumerable<decimal?> source)
247                 {
248                         Check.Source (source);
249
250                         return source.AverageNullable<decimal, decimal, decimal> ((a, b) => a + b, (a, b) => a / b);
251                 }
252
253                 public static float? Average (this IEnumerable<float?> source)
254                 {
255                         Check.Source (source);
256
257                         return source.AverageNullable<float, double, float> ((a, b) => a + b, (a, b) => (float) a / (float) b);
258                 }
259
260                 public static double Average<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
261                 {
262                         Check.SourceAndSelector (source, selector);
263
264                         return source.Select (selector).Average<int, long, double> ((a, b) => a + b, (a, b) => (double) a / (double) b);
265                 }
266
267                 public static double? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
268                 {
269                         Check.SourceAndSelector (source, selector);
270
271                         return source.Select (selector).AverageNullable<int, long, double> ((a, b) => a + b, (a, b) => (double) a / (double) b);
272                 }
273
274                 public static double Average<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
275                 {
276                         Check.SourceAndSelector (source, selector);
277
278                         return source.Select (selector).Average<long, long, double> ((a, b) => a + b, (a, b) => (double) a / (double) b);
279                 }
280
281                 public static double? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
282                 {
283                         Check.SourceAndSelector (source, selector);
284
285                         return source.Select (selector).AverageNullable<long, long, double> ((a, b) => a + b, (a, b) => (double) a / (double) b);
286                 }
287
288                 public static double Average<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
289                 {
290                         Check.SourceAndSelector (source, selector);
291
292                         return source.Select (selector).Average<double, double, double> ((a, b) => a + b, (a, b) => a / b);
293                 }
294
295                 public static double? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
296                 {
297                         Check.SourceAndSelector (source, selector);
298
299                         return source.Select (selector).AverageNullable<double, double, double> ((a, b) => a + b, (a, b) => a / b);
300                 }
301
302                 public static float Average<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
303                 {
304                         Check.SourceAndSelector (source, selector);
305
306                         return source.Select (selector).Average<float, double, float> ((a, b) => a + b, (a, b) => (float) a / (float) b);
307                 }
308
309                 public static float? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
310                 {
311                         Check.SourceAndSelector (source, selector);
312
313                         return source.Select (selector).AverageNullable<float, double, float> ((a, b) => a + b, (a, b) => (float) a / (float) b);
314                 }
315
316                 public static decimal Average<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
317                 {
318                         Check.SourceAndSelector (source, selector);
319
320                         return source.Select (selector).Average<decimal, decimal, decimal> ((a, b) => a + b, (a, b) => a / b);
321                 }
322
323                 public static decimal? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
324                 {
325                         Check.SourceAndSelector (source, selector);
326
327                         return source.Select (selector).AverageNullable<decimal, decimal, decimal> ((a, b) => a + b, (a, b) => a / b);
328                 }
329
330                 #endregion
331
332                 #region Cast
333
334                 public static IEnumerable<TResult> Cast<TResult> (this IEnumerable source)
335                 {
336                         Check.Source (source);
337
338                         return CreateCastIterator<TResult> (source);
339                 }
340
341                 static IEnumerable<TResult> CreateCastIterator<TResult> (IEnumerable source)
342                 {
343                         foreach (TResult element in source)
344                                 yield return element;
345                 }
346
347                 #endregion
348
349                 #region Concat
350
351                 public static IEnumerable<TSource> Concat<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
352                 {
353                         Check.FirstAndSecond (first, second);
354
355                         return CreateConcatIterator (first, second);
356                 }
357
358                 static IEnumerable<TSource> CreateConcatIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second)
359                 {
360                         foreach (TSource element in first)
361                                 yield return element;
362                         foreach (TSource element in second)
363                                 yield return element;
364                 }
365
366                 #endregion
367
368                 #region Contains
369
370                 public static bool Contains<TSource> (this IEnumerable<TSource> source, TSource value)
371                 {
372                         var collection = source as ICollection<TSource>;
373                         if (collection != null)
374                                 return collection.Contains (value);
375
376                         return Contains<TSource> (source, value, null);
377                 }
378
379                 public static bool Contains<TSource> (this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
380                 {
381                         Check.Source (source);
382
383                         if (comparer == null)
384                                 comparer = EqualityComparer<TSource>.Default;
385
386                         foreach (var element in source)
387                                 if (comparer.Equals (element, value))
388                                         return true;
389
390                         return false;
391                 }
392                 #endregion
393
394                 #region Count
395
396                 public static int Count<TSource> (this IEnumerable<TSource> source)
397                 {
398                         Check.Source (source);
399
400                         var collection = source as ICollection<TSource>;
401                         if (collection != null)
402                                 return collection.Count;
403
404                         int counter = 0;
405                         using (var enumerator = source.GetEnumerator ())
406                                 while (enumerator.MoveNext ())
407                                         counter++;
408
409                         return counter;
410                 }
411
412                 public static int Count<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> selector)
413                 {
414                         Check.SourceAndSelector (source, selector);
415
416                         int counter = 0;
417                         foreach (var element in source)
418                                 if (selector (element))
419                                         counter++;
420
421                         return counter;
422                 }
423
424                 #endregion
425
426                 #region DefaultIfEmpty
427
428                 public static IEnumerable<TSource> DefaultIfEmpty<TSource> (this IEnumerable<TSource> source)
429                 {
430                         return DefaultIfEmpty (source, default (TSource));
431                 }
432
433                 public static IEnumerable<TSource> DefaultIfEmpty<TSource> (this IEnumerable<TSource> source, TSource defaultValue)
434                 {
435                         Check.Source (source);
436
437                         return CreateDefaultIfEmptyIterator (source, defaultValue);
438                 }
439
440                 static IEnumerable<TSource> CreateDefaultIfEmptyIterator<TSource> (IEnumerable<TSource> source, TSource defaultValue)
441                 {
442                         bool empty = true;
443                         foreach (TSource item in source) {
444                                 empty = false;
445                                 yield return item;
446                         }
447
448                         if (empty)
449                                 yield return defaultValue;
450                 }
451
452                 #endregion
453
454                 #region Distinct
455
456                 public static IEnumerable<TSource> Distinct<TSource> (this IEnumerable<TSource> source)
457                 {
458                         return Distinct<TSource> (source, null);
459                 }
460
461                 public static IEnumerable<TSource> Distinct<TSource> (this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
462                 {
463                         Check.Source (source);
464
465                         if (comparer == null)
466                                 comparer = EqualityComparer<TSource>.Default;
467
468                         return CreateDistinctIterator (source, comparer);
469                 }
470
471                 static IEnumerable<TSource> CreateDistinctIterator<TSource> (IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
472                 {
473                         var items = new HashSet<TSource> (comparer);
474                         foreach (var element in source) {
475                                 if (! items.Contains (element)) {
476                                         items.Add (element);
477                                         yield return element;
478                                 }
479                         }
480                 }
481
482                 #endregion
483
484                 #region ElementAt
485
486                 static TSource ElementAt<TSource> (this IEnumerable<TSource> source, int index, Fallback fallback)
487                 {
488                         long counter = 0L;
489
490                         foreach (var element in source) {
491                                 if (index == counter++)
492                                         return element;
493                         }
494
495                         if (fallback == Fallback.Throw)
496                                 throw new ArgumentOutOfRangeException ();
497
498                         return default (TSource);
499                 }
500
501                 public static TSource ElementAt<TSource> (this IEnumerable<TSource> source, int index)
502                 {
503                         Check.Source (source);
504
505                         if (index < 0)
506                                 throw new ArgumentOutOfRangeException ();
507
508                         var list = source as IList<TSource>;
509                         if (list != null)
510                                 return list [index];
511
512                         return source.ElementAt (index, Fallback.Throw);
513                 }
514
515                 #endregion
516
517                 #region ElementAtOrDefault
518
519                 public static TSource ElementAtOrDefault<TSource> (this IEnumerable<TSource> source, int index)
520                 {
521                         Check.Source (source);
522
523                         if (index < 0)
524                                 return default (TSource);
525
526                         var list = source as IList<TSource>;
527                         if (list != null)
528                                 return index < list.Count ? list [index] : default (TSource);
529
530                         return source.ElementAt (index, Fallback.Default);
531                 }
532
533                 #endregion
534
535                 #region Empty
536
537                 public static IEnumerable<TResult> Empty<TResult> ()
538                 {
539                         return new TResult [0];
540                 }
541
542                 #endregion
543
544                 #region Except
545
546                 public static IEnumerable<TSource> Except<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
547                 {
548                         return Except (first, second, null);
549                 }
550
551                 public static IEnumerable<TSource> Except<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
552                 {
553                         Check.FirstAndSecond (first, second);
554
555                         if (comparer == null)
556                                 comparer = EqualityComparer<TSource>.Default;
557
558                         return CreateExceptIterator (first, second, comparer);
559                 }
560
561                 static IEnumerable<TSource> CreateExceptIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
562                 {
563                         var items = new HashSet<TSource> (second, comparer);
564                         foreach (var element in first) {
565                                 if (!items.Contains (element, comparer))
566                                         yield return element;
567                         }
568                 }
569
570                 #endregion
571
572                 #region First
573
574                 static TSource First<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate, Fallback fallback)
575                 {
576                         foreach (var element in source)
577                                 if (predicate (element))
578                                         return element;
579
580                         if (fallback == Fallback.Throw)
581                                 throw new InvalidOperationException ();
582
583                         return default (TSource);
584                 }
585
586                 public static TSource First<TSource> (this IEnumerable<TSource> source)
587                 {
588                         Check.Source (source);
589
590                         var list = source as IList<TSource>;
591                         if (list != null) {
592                                 if (list.Count != 0)
593                                         return list [0];
594
595                                 throw new InvalidOperationException ();
596                         } else {
597                                 using (var enumerator = source.GetEnumerator ()) {
598                                         if (enumerator.MoveNext ())
599                                                 return enumerator.Current;
600                                 }
601                         }
602
603                         throw new InvalidOperationException ();
604                 }
605
606                 public static TSource First<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
607                 {
608                         Check.SourceAndPredicate (source, predicate);
609
610                         return source.First (predicate, Fallback.Throw);
611                 }
612
613                 #endregion
614
615                 #region FirstOrDefault
616
617                 public static TSource FirstOrDefault<TSource> (this IEnumerable<TSource> source)
618                 {
619                         Check.Source (source);
620
621                         return source.First (PredicateOf<TSource>.Always, Fallback.Default);
622                 }
623
624                 public static TSource FirstOrDefault<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
625                 {
626                         Check.SourceAndPredicate (source, predicate);
627
628                         return source.First (predicate, Fallback.Default);
629                 }
630
631                 #endregion
632
633                 #region GroupBy
634
635                 private static List<T> ContainsGroup<K, T> (
636                                 Dictionary<K, List<T>> items, K key, IEqualityComparer<K> comparer)
637                 {
638                         IEqualityComparer<K> comparerInUse = (comparer ?? EqualityComparer<K>.Default);
639                         foreach (KeyValuePair<K, List<T>> value in items) {
640                                 if (comparerInUse.Equals (value.Key, key))
641                                         return value.Value;
642                         }
643                         return null;
644                 }
645
646                 public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this IEnumerable<TSource> source,
647                         Func<TSource, TKey> keySelector)
648                 {
649                         return GroupBy<TSource, TKey> (source, keySelector, null);
650                 }
651
652                 public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this IEnumerable<TSource> source,
653                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
654                 {
655                         Check.SourceAndKeySelector (source, keySelector);
656
657                         return CreateGroupByIterator (source, keySelector, comparer);
658                 }
659
660                 static IEnumerable<IGrouping<TKey, TSource>> CreateGroupByIterator<TSource, TKey> (this IEnumerable<TSource> source,
661                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
662                 {
663                         Dictionary<TKey, List<TSource>> groups = new Dictionary<TKey, List<TSource>> ();
664                         List<TSource> nullList = new List<TSource> ();
665                         int counter = 0;
666                         int nullCounter = -1;
667
668                         foreach (TSource element in source) {
669                                 TKey key = keySelector (element);
670                                 if (key == null) {
671                                         nullList.Add (element);
672                                         if (nullCounter == -1) {
673                                                 nullCounter = counter;
674                                                 counter++;
675                                         }
676                                 } else {
677                                         List<TSource> group = ContainsGroup<TKey, TSource> (groups, key, comparer);
678                                         if (group == null) {
679                                                 group = new List<TSource> ();
680                                                 groups.Add (key, group);
681                                                 counter++;
682                                         }
683                                         group.Add (element);
684                                 }
685                         }
686
687                         counter = 0;
688                         foreach (KeyValuePair<TKey, List<TSource>> group in groups) {
689                                 if (counter == nullCounter) {
690                                         Grouping<TKey, TSource> nullGroup = new Grouping<TKey, TSource> (default (TKey), nullList);
691                                         yield return nullGroup;
692                                         counter++;
693                                 }
694                                 Grouping<TKey, TSource> grouping = new Grouping<TKey, TSource> (group.Key, group.Value);
695                                 yield return grouping;
696                                 counter++;
697                         }
698                 }
699
700                 public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this IEnumerable<TSource> source,
701                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
702                 {
703                         return GroupBy<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
704                 }
705
706                 public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this IEnumerable<TSource> source,
707                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
708                 {
709                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
710
711                         Dictionary<TKey, List<TElement>> groups = new Dictionary<TKey, List<TElement>> ();
712                         List<TElement> nullList = new List<TElement> ();
713                         int counter = 0;
714                         int nullCounter = -1;
715
716                         foreach (TSource item in source) {
717                                 TKey key = keySelector (item);
718                                 TElement element = elementSelector (item);
719                                 if (key == null) {
720                                         nullList.Add (element);
721                                         if (nullCounter == -1) {
722                                                 nullCounter = counter;
723                                                 counter++;
724                                         }
725                                 } else {
726                                         List<TElement> group = ContainsGroup<TKey, TElement> (groups, key, comparer);
727                                         if (group == null) {
728                                                 group = new List<TElement> ();
729                                                 groups.Add (key, group);
730                                                 counter++;
731                                         }
732                                         group.Add (element);
733                                 }
734                         }
735
736                         counter = 0;
737                         foreach (KeyValuePair<TKey, List<TElement>> group in groups) {
738                                 if (counter == nullCounter) {
739                                         Grouping<TKey, TElement> nullGroup = new Grouping<TKey, TElement> (default (TKey), nullList);
740                                         yield return nullGroup;
741                                         counter++;
742                                 }
743                                 Grouping<TKey, TElement> grouping = new Grouping<TKey, TElement> (group.Key, group.Value);
744                                 yield return grouping;
745                                 counter++;
746                         }
747                 }
748
749                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult> (this IEnumerable<TSource> source,
750                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector,
751                         Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
752                 {
753                         return GroupBy (source, keySelector, elementSelector, resultSelector, null);
754                 }
755
756                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult> (this IEnumerable<TSource> source,
757                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector,
758                         Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
759                         IEqualityComparer<TKey> comparer)
760                 {
761                         IEnumerable<IGrouping<TKey, TElement>> groups = GroupBy<TSource, TKey, TElement> (
762                                 source, keySelector, elementSelector, comparer);
763
764                         foreach (IGrouping<TKey, TElement> group in groups)
765                                 yield return resultSelector (group.Key, group);
766                 }
767
768                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult> (this IEnumerable<TSource> source,
769                         Func<TSource, TKey> keySelector,
770                         Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
771                 {
772                         return GroupBy (source, keySelector, resultSelector, null);
773                 }
774
775                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult> (this IEnumerable<TSource> source,
776                         Func<TSource, TKey> keySelector,
777                         Func<TKey, IEnumerable<TSource>, TResult> resultSelector,
778                         IEqualityComparer<TKey> comparer)
779                 {
780                         IEnumerable<IGrouping<TKey,TSource>> groups = GroupBy<TSource, TKey> (source, keySelector, comparer);
781
782                         foreach (IGrouping<TKey, TSource> group in groups)
783                                 yield return resultSelector (group.Key, group);
784                 }
785
786                 #endregion
787
788                 # region GroupJoin
789
790                 public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
791                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
792                         Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
793                 {
794                         return GroupJoin (outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
795                 }
796
797                 public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
798                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
799                         Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
800                         IEqualityComparer<TKey> comparer)
801                 {
802                         Check.JoinSelectors (outer, inner, outerKeySelector, innerKeySelector, resultSelector);
803
804                         if (comparer == null)
805                                 comparer = EqualityComparer<TKey>.Default;
806
807                         return CreateGroupJoinIterator (outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
808                 }
809
810                 static IEnumerable<TResult> CreateGroupJoinIterator<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
811                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
812                         Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
813                         IEqualityComparer<TKey> comparer)
814                 {
815                         ILookup<TKey, TInner> innerKeys = ToLookup<TInner, TKey> (inner, innerKeySelector, comparer);
816                         /*Dictionary<K, List<U>> innerKeys = new Dictionary<K, List<U>> ();
817                         foreach (U element in inner)
818                         {
819                                         K innerKey = innerKeySelector (element);
820                                         if (!innerKeys.ContainsKey (innerKey))
821                                                         innerKeys.Add (innerKey, new List<U> ());
822                                         innerKeys[innerKey].Add (element);
823                         }*/
824
825                         foreach (TOuter element in outer) {
826                                 TKey outerKey = outerKeySelector (element);
827                                 if (innerKeys.Contains (outerKey))
828                                         yield return resultSelector (element, innerKeys [outerKey]);
829                                 else
830                                         yield return resultSelector (element, Empty<TInner> ());
831                         }
832                 }
833
834                 #endregion
835
836                 #region Intersect
837
838                 public static IEnumerable<TSource> Intersect<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
839                 {
840                         return Intersect (first, second, null);
841                 }
842
843                 public static IEnumerable<TSource> Intersect<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
844                 {
845                         Check.FirstAndSecond (first, second);
846
847                         if (comparer == null)
848                                 comparer = EqualityComparer<TSource>.Default;
849
850                         return CreateIntersectIterator (first, second, comparer);
851                 }
852
853                 static IEnumerable<TSource> CreateIntersectIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
854                 {
855                         var items = new HashSet<TSource> (second, comparer);
856                         foreach (TSource element in first) {
857                                 if (items.Contains (element))
858                                         yield return element;
859                         }
860                 }
861
862                 #endregion
863
864                 # region Join
865
866                 public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
867                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
868                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
869                 {
870                         Check.JoinSelectors (outer, inner, outerKeySelector, innerKeySelector, resultSelector);
871
872                         if (comparer == null)
873                                 comparer = EqualityComparer<TKey>.Default;
874
875                         return CreateJoinIterator (outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
876                 }
877
878                 static IEnumerable<TResult> CreateJoinIterator<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
879                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
880                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
881                 {
882                         ILookup<TKey, TInner> innerKeys = ToLookup<TInner, TKey> (inner, innerKeySelector, comparer);
883                         /*Dictionary<K, List<U>> innerKeys = new Dictionary<K, List<U>> ();
884                         foreach (U element in inner)
885                         {
886                                         K innerKey = innerKeySelector (element);
887                                         if (!innerKeys.ContainsKey (innerKey))
888                                                         innerKeys.Add (innerKey, new List<U> ());
889                                         innerKeys[innerKey].Add (element);
890                         }*/
891
892                         foreach (TOuter element in outer) {
893                                 TKey outerKey = outerKeySelector (element);
894                                 if (innerKeys.Contains (outerKey)) {
895                                         foreach (TInner innerElement in innerKeys [outerKey])
896                                                 yield return resultSelector (element, innerElement);
897                                 }
898                         }
899                 }
900
901                 public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
902                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
903                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector)
904                 {
905                         return outer.Join (inner, outerKeySelector, innerKeySelector, resultSelector, null);
906                 }
907
908                 #endregion
909
910                 #region Last
911
912                 static TSource Last<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate, Fallback fallback)
913                 {
914                         var empty = true;
915                         var item = default (TSource);
916
917                         foreach (var element in source) {
918                                 if (!predicate (element))
919                                         continue;
920
921                                 item = element;
922                                 empty = false;
923                         }
924
925                         if (!empty)
926                                 return item;
927
928                         if (fallback == Fallback.Throw)
929                                 throw new InvalidOperationException ();
930
931                         return item;
932                 }
933
934                 public static TSource Last<TSource> (this IEnumerable<TSource> source)
935                 {
936                         Check.Source (source);
937
938                         var collection = source as ICollection<TSource>;
939                         if (collection != null && collection.Count == 0)
940                                 throw new InvalidOperationException ();
941
942                         var list = source as IList<TSource>;
943                         if (list != null)
944                                 return list [list.Count - 1];
945
946                         return source.Last (PredicateOf<TSource>.Always, Fallback.Throw);
947                 }
948
949                 public static TSource Last<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
950                 {
951                         Check.SourceAndPredicate (source, predicate);
952
953                         return source.Last (predicate, Fallback.Throw);
954                 }
955
956                 #endregion
957
958                 #region LastOrDefault
959
960                 public static TSource LastOrDefault<TSource> (this IEnumerable<TSource> source)
961                 {
962                         Check.Source (source);
963
964                         var list = source as IList<TSource>;
965                         if (list != null)
966                                 return list.Count > 0 ? list [list.Count - 1] : default (TSource);
967
968                         return source.Last (PredicateOf<TSource>.Always, Fallback.Default);
969                 }
970
971                 public static TSource LastOrDefault<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
972                 {
973                         Check.SourceAndPredicate (source, predicate);
974
975                         return source.Last (predicate, Fallback.Default);
976                 }
977
978                 #endregion
979
980                 #region LongCount
981
982                 public static long LongCount<TSource> (this IEnumerable<TSource> source)
983                 {
984                         Check.Source (source);
985
986 #if !NET_2_1
987                         var array = source as TSource [];
988                         if (array != null)
989                                 return array.LongLength;
990 #endif
991
992                         long counter = 0;
993                         using (var enumerator = source.GetEnumerator ())
994                                 while (enumerator.MoveNext ())
995                                         counter++;
996
997                         return counter;
998                 }
999
1000                 public static long LongCount<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> selector)
1001                 {
1002                         Check.SourceAndSelector (source, selector);
1003
1004                         long counter = 0;
1005                         foreach (TSource element in source)
1006                                 if (selector (element))
1007                                         counter++;
1008
1009                         return counter;
1010                 }
1011
1012                 #endregion
1013
1014                 #region Max
1015
1016                 public static int Max (this IEnumerable<int> source)
1017                 {
1018                         Check.Source (source);
1019
1020                         return Iterate (source, int.MinValue, (a, b) => Math.Max (a, b));
1021                 }
1022
1023                 public static long Max (this IEnumerable<long> source)
1024                 {
1025                         Check.Source (source);
1026
1027                         return Iterate (source, long.MinValue, (a, b) => Math.Max (a, b));
1028                 }
1029
1030                 public static double Max (this IEnumerable<double> source)
1031                 {
1032                         Check.Source (source);
1033
1034                         return Iterate (source, double.MinValue, (a, b) => Math.Max (a, b));
1035                 }
1036
1037                 public static float Max (this IEnumerable<float> source)
1038                 {
1039                         Check.Source (source);
1040
1041                         return Iterate (source, float.MinValue, (a, b) => Math.Max (a, b));
1042                 }
1043
1044                 public static decimal Max (this IEnumerable<decimal> source)
1045                 {
1046                         Check.Source (source);
1047
1048                         return Iterate (source, decimal.MinValue, (a, b) => Math.Max (a, b));
1049                 }
1050
1051                 public static int? Max (this IEnumerable<int?> source)
1052                 {
1053                         Check.Source (source);
1054
1055                         return IterateNullable (source, int.MinValue, (a, b) => a > b);
1056                 }
1057
1058                 public static long? Max (this IEnumerable<long?> source)
1059                 {
1060                         Check.Source (source);
1061
1062                         return IterateNullable (source, long.MinValue, (a, b) => a > b);
1063                 }
1064
1065                 public static double? Max (this IEnumerable<double?> source)
1066                 {
1067                         Check.Source (source);
1068
1069                         return IterateNullable (source, double.MinValue, (a, b) => a > b);
1070                 }
1071
1072                 public static float? Max (this IEnumerable<float?> source)
1073                 {
1074                         Check.Source (source);
1075
1076                         return IterateNullable (source, float.MinValue, (a, b) => a > b);
1077                 }
1078
1079                 public static decimal? Max (this IEnumerable<decimal?> source)
1080                 {
1081                         Check.Source (source);
1082
1083                         return IterateNullable (source, decimal.MinValue, (a, b) => a > b);
1084                 }
1085
1086                 static T? IterateNullable<T> (IEnumerable<T?> source, T initValue, Func<T?, T?, bool> selector) where T : struct
1087                 {
1088                         bool empty = true;
1089                         T? value = initValue;
1090                         foreach (var element in source) {
1091                                 if (!element.HasValue)
1092                                         continue;
1093
1094                                 if (selector (element.Value, value))
1095                                         value = element;
1096
1097                                 empty = false;
1098                         }
1099
1100                         if (empty)
1101                                 return null;
1102
1103                         return value;
1104                 }
1105
1106                 public static TSource Max<TSource> (this IEnumerable<TSource> source)
1107                 {
1108                         Check.Source (source);
1109
1110                         bool notAssigned = true;
1111                         TSource maximum = default (TSource);
1112                         int counter = 0;
1113                         foreach (TSource element in source) {
1114                                 if (notAssigned) {
1115                                         maximum = element;
1116                                         notAssigned = false;
1117                                 } else {
1118                                         int comparison;
1119                                         if (element is IComparable<TSource>)
1120                                                 comparison = ((IComparable<TSource>) element).CompareTo (maximum);
1121                                         else if (element is System.IComparable)
1122                                                 comparison = ((System.IComparable) element).CompareTo (maximum);
1123                                         else
1124                                                 throw new ArgumentNullException ();
1125
1126                                         if (comparison > 0)
1127                                                 maximum = element;
1128                                 }
1129                                 counter++;
1130                         }
1131
1132                         if (counter == 0)
1133                                 throw new InvalidOperationException ();
1134                         else
1135                                 return maximum;
1136                 }
1137
1138                 public static int Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1139                 {
1140                         Check.SourceAndSelector (source, selector);
1141
1142                         return Iterate (source, int.MinValue, (a, b) => Math.Max (selector (a), b));
1143                 }
1144
1145                 public static long Max<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1146                 {
1147                         Check.SourceAndSelector (source, selector);
1148
1149                         return Iterate (source, long.MinValue, (a, b) => Math.Max (selector (a), b));
1150                 }
1151
1152                 public static double Max<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1153                 {
1154                         Check.SourceAndSelector (source, selector);
1155
1156                         return Iterate (source, double.MinValue, (a, b) => Math.Max (selector (a), b));
1157                 }
1158
1159                 public static float Max<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1160                 {
1161                         Check.SourceAndSelector (source, selector);
1162
1163                         return Iterate (source, float.MinValue, (a, b) => Math.Max (selector (a), b));
1164                 }
1165
1166                 public static decimal Max<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1167                 {
1168                         Check.SourceAndSelector (source, selector);
1169
1170                         return Iterate (source, decimal.MinValue, (a, b) => Math.Max (selector (a), b));
1171                 }
1172
1173                 static U Iterate<T, U> (IEnumerable<T> source, U initValue, Func<T, U, U> selector)
1174                 {
1175                         bool empty = true;
1176                         foreach (var element in source) {
1177                                 initValue = selector (element, initValue);
1178                                 empty = false;
1179                         }
1180
1181                         if (empty)
1182                                 throw new InvalidOperationException ();
1183
1184                         return initValue;
1185                 }
1186
1187                 static U? IterateNullable<T, U> (IEnumerable<T> source, U initialValue, Func<T, U?, U?> selector) where U : struct
1188                 {
1189                         bool empty = true;
1190                         U? value = initialValue;
1191                         foreach (var element in source) {
1192                                 value = selector (element, value);
1193                                 if (!value.HasValue)
1194                                         continue;
1195
1196                                 empty = false;
1197                         }
1198
1199                         if (empty)
1200                                 return null;
1201
1202                         return value;
1203                 }
1204
1205                 public static int? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1206                 {
1207                         Check.SourceAndSelector (source, selector);
1208
1209                         return IterateNullable (source, int.MinValue, (a, b) => {
1210                                 var v = selector (a); return v > b ? v : b;
1211                         });
1212                 }
1213
1214                 public static long? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1215                 {
1216                         Check.SourceAndSelector (source, selector);
1217
1218                         return IterateNullable (source, long.MinValue, (a, b) => {
1219                                 var v = selector (a); return v > b ? v : b;
1220                         });
1221                 }
1222
1223                 public static double? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1224                 {
1225                         Check.SourceAndSelector (source, selector);
1226
1227                         return IterateNullable (source, double.MinValue, (a, b) => {
1228                                 var v = selector (a); return v > b ? v : b;
1229                         });
1230                 }
1231
1232                 public static float? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1233                 {
1234                         Check.SourceAndSelector (source, selector);
1235
1236                         return IterateNullable (source, float.MinValue, (a, b) => {
1237                                 var v = selector (a); return v > b ? v : b;
1238                         });
1239                 }
1240
1241                 public static decimal? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1242                 {
1243                         Check.SourceAndSelector (source, selector);
1244
1245                         return IterateNullable (source, decimal.MinValue, (a, b) => {
1246                                 var v = selector (a); return v > b ? v : b;
1247                         });
1248                 }
1249
1250                 public static TResult Max<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1251                 {
1252                         Check.SourceAndSelector (source, selector);
1253
1254                         bool notAssigned = true;
1255                         TResult maximum = default (TResult);
1256                         int counter = 0;
1257                         foreach (TSource item in source) {
1258                                 TResult element = selector (item);
1259                                 if (notAssigned) {
1260                                         maximum = element;
1261                                         notAssigned = false;
1262                                 } else {
1263                                         int comparison;
1264                                         if (element is IComparable<TResult>)
1265                                                 comparison = ((IComparable<TResult>) element).CompareTo (maximum);
1266                                         else if (element is System.IComparable)
1267                                                 comparison = ((System.IComparable) element).CompareTo (maximum);
1268                                         else
1269                                                 throw new ArgumentNullException ();
1270
1271                                         if (comparison > 0)
1272                                                 maximum = element;
1273                                 }
1274                                 counter++;
1275                         }
1276
1277                         if (counter == 0)
1278                                 throw new InvalidOperationException ();
1279                         else
1280                                 return maximum;
1281                 }
1282
1283                 #endregion
1284
1285                 #region Min
1286
1287                 public static int Min (this IEnumerable<int> source)
1288                 {
1289                         Check.Source (source);
1290
1291                         return Iterate (source, int.MaxValue, (a, b) => Math.Min (a, b));
1292                 }
1293
1294                 public static long Min (this IEnumerable<long> source)
1295                 {
1296                         Check.Source (source);
1297
1298                         return Iterate (source, long.MaxValue, (a, b) => Math.Min (a, b));
1299                 }
1300
1301                 public static double Min (this IEnumerable<double> source)
1302                 {
1303                         Check.Source (source);
1304
1305                         return Iterate (source, double.MaxValue, (a, b) => Math.Min (a, b));
1306                 }
1307
1308                 public static float Min (this IEnumerable<float> source)
1309                 {
1310                         Check.Source (source);
1311
1312                         return Iterate (source, float.MaxValue, (a, b) => Math.Min (a, b));
1313                 }
1314
1315                 public static decimal Min (this IEnumerable<decimal> source)
1316                 {
1317                         Check.Source (source);
1318
1319                         return Iterate (source, decimal.MaxValue, (a, b) => Math.Min (a, b));
1320                 }
1321
1322                 public static int? Min (this IEnumerable<int?> source)
1323                 {
1324                         Check.Source (source);
1325
1326                         return IterateNullable (source, int.MaxValue, (a, b) => a < b);
1327                 }
1328
1329                 public static long? Min (this IEnumerable<long?> source)
1330                 {
1331                         Check.Source (source);
1332
1333                         return IterateNullable (source, long.MaxValue, (a, b) => a < b);
1334                 }
1335
1336                 public static double? Min (this IEnumerable<double?> source)
1337                 {
1338                         Check.Source (source);
1339
1340                         return IterateNullable (source, double.MaxValue, (a, b) => a < b);
1341                 }
1342
1343                 public static float? Min (this IEnumerable<float?> source)
1344                 {
1345                         Check.Source (source);
1346
1347                         return IterateNullable (source, float.MaxValue, (a, b) => a < b);
1348                 }
1349
1350                 public static decimal? Min (this IEnumerable<decimal?> source)
1351                 {
1352                         Check.Source (source);
1353
1354                         return IterateNullable (source, decimal.MaxValue, (a, b) => a < b);
1355                 }
1356
1357                 public static TSource Min<TSource> (this IEnumerable<TSource> source)
1358                 {
1359                         Check.Source (source);
1360
1361                         bool notAssigned = true;
1362                         TSource minimum = default (TSource);
1363                         int counter = 0;
1364                         foreach (TSource element in source) {
1365                                 if (notAssigned) {
1366                                         minimum = element;
1367                                         notAssigned = false;
1368                                 } else {
1369                                         int comparison;
1370                                         if (element is IComparable<TSource>)
1371                                                 comparison = ((IComparable<TSource>) element).CompareTo (minimum);
1372                                         else if (element is System.IComparable)
1373                                                 comparison = ((System.IComparable) element).CompareTo (minimum);
1374                                         else
1375                                                 throw new ArgumentNullException ();
1376
1377                                         if (comparison < 0)
1378                                                 minimum = element;
1379                                 }
1380                                 counter++;
1381                         }
1382
1383                         if (counter == 0)
1384                                 throw new InvalidOperationException ();
1385                         else
1386                                 return minimum;
1387                 }
1388
1389                 public static int Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1390                 {
1391                         Check.SourceAndSelector (source, selector);
1392
1393                         return Iterate (source, int.MaxValue, (a, b) => Math.Min (selector (a), b));
1394                 }
1395
1396                 public static long Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1397                 {
1398                         Check.SourceAndSelector (source, selector);
1399
1400                         return Iterate (source, long.MaxValue, (a, b) => Math.Min (selector (a), b));
1401                 }
1402
1403                 public static double Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1404                 {
1405                         Check.SourceAndSelector (source, selector);
1406
1407                         return Iterate (source, double.MaxValue, (a, b) => Math.Min (selector (a), b));
1408                 }
1409
1410                 public static float Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1411                 {
1412                         Check.SourceAndSelector (source, selector);
1413
1414                         return Iterate (source, float.MaxValue, (a, b) => Math.Min (selector (a), b));
1415                 }
1416
1417                 public static decimal Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1418                 {
1419                         Check.SourceAndSelector (source, selector);
1420
1421                         return Iterate (source, decimal.MaxValue, (a, b) => Math.Min (selector (a), b));
1422                 }
1423
1424                 public static int? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1425                 {
1426                         Check.SourceAndSelector (source, selector);
1427
1428                         return IterateNullable (source, int.MaxValue, (a, b) => {
1429                                 var v = selector (a); return v < b ? v : b;
1430                         });
1431                 }
1432
1433                 public static long? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1434                 {
1435                         Check.SourceAndSelector (source, selector);
1436
1437                         return IterateNullable (source, long.MaxValue, (a, b) => {
1438                                 var v = selector (a); return v < b ? v : b;
1439                         });
1440                 }
1441
1442                 public static float? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1443                 {
1444                         Check.SourceAndSelector (source, selector);
1445
1446                         return IterateNullable (source, float.MaxValue, (a, b) => {
1447                                 var v = selector (a); return v < b ? v : b;
1448                         });
1449                 }
1450
1451                 public static double? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1452                 {
1453                         Check.SourceAndSelector (source, selector);
1454
1455                         return IterateNullable (source, double.MaxValue, (a, b) => {
1456                                 var v = selector (a); return v < b ? v : b;
1457                         });
1458                 }
1459
1460                 public static decimal? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1461                 {
1462                         Check.SourceAndSelector (source, selector);
1463
1464                         return IterateNullable (source, decimal.MaxValue, (a, b) => {
1465                                 var v = selector (a); return v < b ? v : b;
1466                         });
1467                 }
1468
1469                 public static TResult Min<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1470                 {
1471                         Check.SourceAndSelector (source, selector);
1472
1473                         bool notAssigned = true;
1474                         TResult minimum = default (TResult);
1475                         int counter = 0;
1476                         foreach (TSource item in source) {
1477                                 TResult element = selector (item);
1478                                 if (notAssigned) {
1479                                         minimum = element;
1480                                         notAssigned = false;
1481                                 } else {
1482                                         int comparison;
1483                                         if (element is IComparable<TResult>)
1484                                                 comparison = ((IComparable<TResult>) element).CompareTo (minimum);
1485                                         else if (element is System.IComparable)
1486                                                 comparison = ((System.IComparable) element).CompareTo (minimum);
1487                                         else
1488                                                 throw new ArgumentNullException ();
1489
1490                                         if (comparison < 0)
1491                                                 minimum = element;
1492                                 }
1493                                 counter++;
1494                         }
1495
1496                         if (counter == 0)
1497                                 throw new InvalidOperationException ();
1498                         else
1499                                 return minimum;
1500                 }
1501
1502                 #endregion
1503
1504                 #region OfType
1505
1506                 public static IEnumerable<TResult> OfType<TResult> (this IEnumerable source)
1507                 {
1508                         Check.Source (source);
1509
1510                         return CreateOfTypeIterator<TResult> (source);
1511                 }
1512
1513                 static IEnumerable<TResult> CreateOfTypeIterator<TResult> (IEnumerable source)
1514                 {
1515                         foreach (object element in source)
1516                                 if (element is TResult)
1517                                         yield return (TResult) element;
1518                 }
1519
1520                 #endregion
1521
1522                 #region OrderBy
1523
1524                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
1525                                 Func<TSource, TKey> keySelector)
1526                 {
1527                         return OrderBy<TSource, TKey> (source, keySelector, null);
1528                 }
1529
1530                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
1531                                 Func<TSource, TKey> keySelector,
1532                                 IComparer<TKey> comparer)
1533                 {
1534                         Check.SourceAndKeySelector (source, keySelector);
1535
1536                         return new OrderedSequence<TSource, TKey> (source, keySelector, comparer, SortDirection.Ascending);
1537                 }
1538
1539                 #endregion
1540
1541                 #region OrderByDescending
1542
1543                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
1544                                 Func<TSource, TKey> keySelector)
1545                 {
1546                         return OrderByDescending<TSource, TKey> (source, keySelector, null);
1547                 }
1548
1549                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
1550                                 Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
1551                 {
1552                         Check.SourceAndKeySelector (source, keySelector);
1553
1554                         return new OrderedSequence<TSource, TKey> (source, keySelector, comparer, SortDirection.Descending);
1555                 }
1556
1557                 #endregion
1558
1559                 #region Range
1560
1561                 public static IEnumerable<int> Range (int start, int count)
1562                 {
1563                         if (count < 0)
1564                                 throw new ArgumentOutOfRangeException ("count");
1565
1566                         long upto = ((long) start + count) - 1;
1567
1568                         if (upto > int.MaxValue)
1569                                 throw new ArgumentOutOfRangeException ();
1570
1571                         return CreateRangeIterator (start, (int) upto);
1572                 }
1573
1574                 static IEnumerable<int> CreateRangeIterator (int start, int upto)
1575                 {
1576                         for (int i = start; i <= upto; i++)
1577                                 yield return i;
1578                 }
1579
1580                 #endregion
1581
1582                 #region Repeat
1583
1584                 public static IEnumerable<TResult> Repeat<TResult> (TResult element, int count)
1585                 {
1586                         if (count < 0)
1587                                 throw new ArgumentOutOfRangeException ();
1588
1589                         return CreateRepeatIterator (element, count);
1590                 }
1591
1592                 static IEnumerable<TResult> CreateRepeatIterator<TResult> (TResult element, int count)
1593                 {
1594                         for (int i = 0; i < count; i++)
1595                                 yield return element;
1596                 }
1597
1598                 #endregion
1599
1600                 #region Reverse
1601
1602                 public static IEnumerable<TSource> Reverse<TSource> (this IEnumerable<TSource> source)
1603                 {
1604                         Check.Source (source);
1605
1606                         var list = source as IList<TSource>;
1607                         if (list == null)
1608                                 list = new List<TSource> (source);
1609
1610                         return CreateReverseIterator (list);
1611                 }
1612
1613                 static IEnumerable<TSource> CreateReverseIterator<TSource> (IList<TSource> source)
1614                 {
1615                         for (int i = source.Count; i > 0; --i)
1616                                 yield return source [i - 1];
1617                 }
1618
1619                 #endregion
1620
1621                 #region Select
1622
1623                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1624                 {
1625                         Check.SourceAndSelector (source, selector);
1626
1627                         return CreateSelectIterator (source, selector);
1628                 }
1629
1630                 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, TResult> selector)
1631                 {
1632                         foreach (var element in source)
1633                                 yield return selector (element);
1634                 }
1635
1636                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
1637                 {
1638                         Check.SourceAndSelector (source, selector);
1639
1640                         return CreateSelectIterator (source, selector);
1641                 }
1642
1643                 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
1644                 {
1645                         int counter = 0;
1646                         foreach (TSource element in source) {
1647                                 yield return selector (element, counter);
1648                                 counter++;
1649                         }
1650                 }
1651
1652                 #endregion
1653
1654                 #region SelectMany
1655
1656                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
1657                 {
1658                         Check.SourceAndSelector (source, selector);
1659
1660                         return CreateSelectManyIterator (source, selector);
1661                 }
1662
1663                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
1664                 {
1665                         foreach (TSource element in source)
1666                                 foreach (TResult item in selector (element))
1667                                         yield return item;
1668                 }
1669
1670                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
1671                 {
1672                         Check.SourceAndSelector (source, selector);
1673
1674                         return CreateSelectManyIterator (source, selector);
1675                 }
1676
1677                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
1678                 {
1679                         int counter = 0;
1680                         foreach (TSource element in source) {
1681                                 foreach (TResult item in selector (element, counter))
1682                                         yield return item;
1683                                 counter++;
1684                         }
1685                 }
1686
1687                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
1688                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1689                 {
1690                         Check.SourceAndCollectionSelectors (source, collectionSelector, selector);
1691
1692                         return CreateSelectManyIterator (source, collectionSelector, selector);
1693                 }
1694
1695                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult> (IEnumerable<TSource> source,
1696                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1697                 {
1698                         foreach (TSource element in source)
1699                                 foreach (TCollection collection in collectionSelector (element))
1700                                         yield return selector (element, collection);
1701                 }
1702
1703                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
1704                         Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1705                 {
1706                         Check.SourceAndCollectionSelectors (source, collectionSelector, selector);
1707
1708                         return CreateSelectManyIterator (source, collectionSelector, selector);
1709                 }
1710
1711                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult> (IEnumerable<TSource> source,
1712                         Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1713                 {
1714                         int counter = 0;
1715                         foreach (TSource element in source)
1716                                 foreach (TCollection collection in collectionSelector (element, counter++))
1717                                         yield return selector (element, collection);
1718                 }
1719
1720                 #endregion
1721
1722                 #region Single
1723
1724                 static TSource Single<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate, Fallback fallback)
1725                 {
1726                         var found = false;
1727                         var item = default (TSource);
1728
1729                         foreach (var element in source) {
1730                                 if (!predicate (element))
1731                                         continue;
1732
1733                                 if (found)
1734                                         throw new InvalidOperationException ();
1735
1736                                 found = true;
1737                                 item = element;
1738                         }
1739
1740                         if (!found && fallback == Fallback.Throw)
1741                                 throw new InvalidOperationException ();
1742
1743                         return item;
1744                 }
1745
1746                 public static TSource Single<TSource> (this IEnumerable<TSource> source)
1747                 {
1748                         Check.Source (source);
1749
1750                         return source.Single (PredicateOf<TSource>.Always, Fallback.Throw);
1751                 }
1752
1753                 public static TSource Single<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1754                 {
1755                         Check.SourceAndPredicate (source, predicate);
1756
1757                         return source.Single (predicate, Fallback.Throw);
1758                 }
1759
1760                 #endregion
1761
1762                 #region SingleOrDefault
1763
1764                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source)
1765                 {
1766                         Check.Source (source);
1767
1768                         return source.Single (PredicateOf<TSource>.Always, Fallback.Default);
1769                 }
1770
1771                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1772                 {
1773                         Check.SourceAndPredicate (source, predicate);
1774
1775                         return source.Single (predicate, Fallback.Default);
1776                 }
1777
1778                 #endregion
1779
1780                 #region Skip
1781
1782                 public static IEnumerable<TSource> Skip<TSource> (this IEnumerable<TSource> source, int count)
1783                 {
1784                         Check.Source (source);
1785
1786                         return CreateSkipIterator (source, count);
1787                 }
1788
1789                 static IEnumerable<TSource> CreateSkipIterator<TSource> (IEnumerable<TSource> source, int count)
1790                 {
1791                         int i = 0;
1792                         foreach (var element in source) {
1793                                 if (i++ < count)
1794                                         continue;
1795
1796                                 yield return element;
1797                         }
1798                 }
1799
1800                 #endregion
1801
1802                 #region SkipWhile
1803
1804                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1805                 {
1806                         Check.SourceAndPredicate (source, predicate);
1807
1808                         return CreateSkipWhileIterator (source, predicate);
1809                 }
1810
1811                 static IEnumerable<TSource> CreateSkipWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
1812                 {
1813                         bool yield = false;
1814
1815                         foreach (TSource element in source) {
1816                                 if (yield)
1817                                         yield return element;
1818                                 else
1819                                         if (!predicate (element)) {
1820                                                 yield return element;
1821                                                 yield = true;
1822                                         }
1823                         }
1824                 }
1825
1826                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
1827                 {
1828                         Check.SourceAndPredicate (source, predicate);
1829
1830                         return CreateSkipWhileIterator (source, predicate);
1831                 }
1832
1833                 static IEnumerable<TSource> CreateSkipWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
1834                 {
1835                         int counter = 0;
1836                         bool yield = false;
1837
1838                         foreach (TSource element in source) {
1839                                 if (yield)
1840                                         yield return element;
1841                                 else
1842                                         if (!predicate (element, counter)) {
1843                                                 yield return element;
1844                                                 yield = true;
1845                                         }
1846                                 counter++;
1847                         }
1848                 }
1849
1850                 #endregion
1851
1852                 #region Sum
1853
1854                 public static int Sum (this IEnumerable<int> source)
1855                 {
1856                         Check.Source (source);
1857
1858                         return Sum<int, int> (source, (a, b) => checked (a + b));
1859                 }
1860
1861                 public static int? Sum (this IEnumerable<int?> source)
1862                 {
1863                         Check.Source (source);
1864
1865                         return source.SumNullable<int?, int?> (0, (total, element) => element.HasValue ? checked (total + element) : total);
1866                 }
1867
1868                 public static int Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1869                 {
1870                         Check.SourceAndSelector (source, selector);
1871
1872                         return Sum<TSource, int> (source, (a, b) => checked (a + selector (b)));
1873                 }
1874
1875                 public static int? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1876                 {
1877                         Check.SourceAndSelector (source, selector);
1878
1879                         return source.SumNullable<TSource, int?> (0, (a, b) => {
1880                                 var value = selector (b);
1881                                 return value.HasValue ? checked (a + value.Value) : a;
1882                         });
1883                 }
1884
1885                 public static long Sum (this IEnumerable<long> source)
1886                 {
1887                         Check.Source (source);
1888
1889                         return Sum<long, long> (source, (a, b) => checked (a + b));
1890                 }
1891
1892                 public static long? Sum (this IEnumerable<long?> source)
1893                 {
1894                         Check.Source (source);
1895
1896                         return source.SumNullable<long?, long?> (0, (total, element) => element.HasValue ? checked (total + element) : total);
1897                 }
1898
1899                 public static long Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1900                 {
1901                         Check.SourceAndSelector (source, selector);
1902
1903                         return Sum<TSource, long> (source, (a, b) => checked (a + selector (b)));
1904                 }
1905
1906                 public static long? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1907                 {
1908                         Check.SourceAndSelector (source, selector);
1909
1910                         return source.SumNullable<TSource, long?> (0, (a, b) => {
1911                                 var value = selector (b);
1912                                 return value.HasValue ? checked (a + value.Value) : a;
1913                         });
1914                 }
1915
1916                 public static double Sum (this IEnumerable<double> source)
1917                 {
1918                         Check.Source (source);
1919
1920                         return Sum<double, double> (source, (a, b) => checked (a + b));
1921                 }
1922
1923                 public static double? Sum (this IEnumerable<double?> source)
1924                 {
1925                         Check.Source (source);
1926
1927                         return source.SumNullable<double?, double?> (0, (total, element) => element.HasValue ? checked (total + element) : total);
1928                 }
1929
1930                 public static double Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1931                 {
1932                         Check.SourceAndSelector (source, selector);
1933
1934                         return Sum<TSource, double> (source, (a, b) => checked (a + selector (b)));
1935                 }
1936
1937                 public static double? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1938                 {
1939                         Check.SourceAndSelector (source, selector);
1940
1941                         return source.SumNullable<TSource, double?> (0, (a, b) => {
1942                                 var value = selector (b);
1943                                 return value.HasValue ? checked (a + value.Value) : a;
1944                         });
1945                 }
1946
1947                 public static float Sum (this IEnumerable<float> source)
1948                 {
1949                         Check.Source (source);
1950
1951                         return Sum<float, float> (source, (a, b) => checked (a + b));
1952                 }
1953
1954                 public static float? Sum (this IEnumerable<float?> source)
1955                 {
1956                         Check.Source (source);
1957
1958                         return source.SumNullable<float?, float?> (0, (total, element) => element.HasValue ? checked (total + element) : total);
1959                 }
1960
1961                 public static float Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1962                 {
1963                         Check.SourceAndSelector (source, selector);
1964
1965                         return Sum<TSource, float> (source, (a, b) => checked (a + selector (b)));
1966                 }
1967
1968                 public static float? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1969                 {
1970                         Check.SourceAndSelector (source, selector);
1971
1972                         return source.SumNullable<TSource, float?> (0, (a, b) => {
1973                                 var value = selector (b);
1974                                 return value.HasValue ? checked (a + value.Value) : a;
1975                         });
1976                 }
1977
1978                 public static decimal Sum (this IEnumerable<decimal> source)
1979                 {
1980                         Check.Source (source);
1981
1982                         return Sum<decimal, decimal> (source, (a, b) => checked (a + b));
1983                 }
1984
1985                 public static decimal? Sum (this IEnumerable<decimal?> source)
1986                 {
1987                         Check.Source (source);
1988
1989                         return source.SumNullable<decimal?, decimal?> (0, (total, element) => element.HasValue ? checked (total + element) : total);
1990                 }
1991
1992                 public static decimal Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1993                 {
1994                         Check.SourceAndSelector (source, selector);
1995
1996                         return Sum<TSource, decimal> (source, (a, b) => checked (a + selector (b)));
1997                 }
1998
1999                 public static decimal? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
2000                 {
2001                         Check.SourceAndSelector (source, selector);
2002
2003                         return source.SumNullable<TSource, decimal?> (0, (a, b) => {
2004                                 var value = selector (b);
2005                                 return value.HasValue ? checked (a + value.Value) : a;
2006                         });
2007                 }
2008
2009                 static TR Sum<TA, TR> (this IEnumerable<TA> source, Func<TR, TA, TR> selector)
2010                 {
2011                         TR total = default (TR);
2012                         long counter = 0;
2013                         foreach (var element in source) {
2014                                 total = selector (total, element);
2015                                 ++counter;
2016                         }
2017
2018                         return total;
2019                 }
2020
2021                 static TR SumNullable<TA, TR> (this IEnumerable<TA> source, TR zero, Func<TR, TA, TR> selector)
2022                 {
2023                         TR total = zero;
2024                         foreach (var element in source) {
2025                                 total = selector (total, element);
2026                         }
2027
2028                         return total;
2029                 }
2030
2031                 #endregion
2032
2033                 #region Take
2034
2035                 public static IEnumerable<TSource> Take<TSource> (this IEnumerable<TSource> source, int count)
2036                 {
2037                         Check.Source (source);
2038
2039                         return CreateTakeIterator (source, count);
2040                 }
2041
2042                 static IEnumerable<TSource> CreateTakeIterator<TSource> (IEnumerable<TSource> source, int count)
2043                 {
2044                         if (count <= 0)
2045                                 yield break;
2046
2047                         int counter = 0;
2048                         foreach (TSource element in source) {
2049                                 yield return element;
2050
2051                                 if (++counter == count)
2052                                         yield break;
2053                         }
2054                 }
2055
2056                 #endregion
2057
2058                 #region TakeWhile
2059
2060                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2061                 {
2062                         Check.SourceAndPredicate (source, predicate);
2063
2064                         return CreateTakeWhileIterator (source, predicate);
2065                 }
2066
2067                 static IEnumerable<TSource> CreateTakeWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
2068                 {
2069                         foreach (var element in source) {
2070                                 if (!predicate (element))
2071                                         yield break;
2072
2073                                 yield return element;
2074                         }
2075                 }
2076
2077                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2078                 {
2079                         Check.SourceAndPredicate (source, predicate);
2080
2081                         return CreateTakeWhileIterator (source, predicate);
2082                 }
2083
2084                 static IEnumerable<TSource> CreateTakeWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2085                 {
2086                         int counter = 0;
2087                         foreach (var element in source) {
2088                                 if (!predicate (element, counter))
2089                                         yield break;
2090
2091                                 yield return element;
2092                                 counter++;
2093                         }
2094                 }
2095
2096                 #endregion
2097
2098                 #region ThenBy
2099
2100                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2101                 {
2102                         return ThenBy<TSource, TKey> (source, keySelector, null);
2103                 }
2104
2105                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2106                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2107                 {
2108                         Check.SourceAndKeySelector (source, keySelector);
2109
2110                         return source.CreateOrderedEnumerable (keySelector, comparer, false);
2111                 }
2112
2113                 #endregion
2114
2115                 #region ThenByDescending
2116
2117                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2118                         Func<TSource, TKey> keySelector)
2119                 {
2120                         return ThenByDescending<TSource, TKey> (source, keySelector, null);
2121                 }
2122
2123                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2124                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2125                 {
2126                         Check.SourceAndKeySelector (source, keySelector);
2127
2128                         return source.CreateOrderedEnumerable (keySelector, comparer, true);
2129                 }
2130
2131                 #endregion
2132
2133                 #region ToArray
2134
2135                 public static TSource [] ToArray<TSource> (this IEnumerable<TSource> source)
2136                 {
2137                         Check.Source (source);
2138
2139                         var collection = source as ICollection<TSource>;
2140                         if (collection != null) {
2141                                 var array = new TSource [collection.Count];
2142                                 collection.CopyTo (array, 0);
2143                                 return array;
2144                         }
2145
2146                         return new List<TSource> (source).ToArray ();
2147                 }
2148
2149                 #endregion
2150
2151                 #region ToDictionary
2152                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2153                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2154                 {
2155                         return ToDictionary<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2156                 }
2157
2158                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2159                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2160                 {
2161                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2162
2163                         if (comparer == null)
2164                                 comparer = EqualityComparer<TKey>.Default;
2165
2166                         var dict = new Dictionary<TKey, TElement> (comparer);
2167                         foreach (var e in source)
2168                                 dict.Add (keySelector (e), elementSelector (e));
2169
2170                         return dict;
2171                 }
2172
2173                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2174                                 Func<TSource, TKey> keySelector)
2175                 {
2176                         return ToDictionary (source, keySelector, null);
2177                 }
2178
2179                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2180                                 Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2181                 {
2182                         return ToDictionary<TSource, TKey, TSource> (source, keySelector, Function<TSource>.Identity, comparer);
2183                 }
2184
2185                 #endregion
2186
2187                 #region ToList
2188                 public static List<TSource> ToList<TSource> (this IEnumerable<TSource> source)
2189                 {
2190                         Check.Source (source);
2191
2192                         return new List<TSource> (source);
2193                 }
2194                 #endregion
2195
2196                 #region ToLookup
2197
2198                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2199                 {
2200                         return ToLookup<TSource, TKey, TSource> (source, keySelector, Function<TSource>.Identity, null);
2201                 }
2202
2203                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source,
2204                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2205                 {
2206                         return ToLookup<TSource, TKey, TSource> (source, keySelector, element => element, comparer);
2207                 }
2208
2209                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2210                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2211                 {
2212                         return ToLookup<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2213                 }
2214
2215                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2216                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2217                 {
2218                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2219
2220                         var dictionary = new Dictionary<TKey, List<TElement>> (comparer ?? EqualityComparer<TKey>.Default);
2221                         foreach (var element in source) {
2222                                 var key = keySelector (element);
2223                                 if (key == null)
2224                                         throw new ArgumentNullException ("key");
2225
2226                                 List<TElement> list;
2227                                 if (!dictionary.TryGetValue (key, out list)) {
2228                                         list = new List<TElement> ();
2229                                         dictionary.Add (key, list);
2230                                 }
2231
2232                                 list.Add (elementSelector (element));
2233                         }
2234
2235                         return new Lookup<TKey, TElement> (dictionary);
2236                 }
2237
2238                 #endregion
2239
2240                 #region SequenceEqual
2241
2242                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2243                 {
2244                         return first.SequenceEqual (second, null);
2245                 }
2246
2247                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2248                 {
2249                         Check.FirstAndSecond (first, second);
2250
2251                         if (comparer == null)
2252                                 comparer = EqualityComparer<TSource>.Default;
2253
2254                         using (IEnumerator<TSource> first_enumerator = first.GetEnumerator (),
2255                                 second_enumerator = second.GetEnumerator ()) {
2256
2257                                 while (first_enumerator.MoveNext ()) {
2258                                         if (!second_enumerator.MoveNext ())
2259                                                 return false;
2260
2261                                         if (!comparer.Equals (first_enumerator.Current, second_enumerator.Current))
2262                                                 return false;
2263                                 }
2264
2265                                 return !second_enumerator.MoveNext ();
2266                         }
2267                 }
2268
2269                 #endregion
2270
2271                 #region Union
2272
2273                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2274                 {
2275                         Check.FirstAndSecond (first, second);
2276
2277                         return first.Union (second, null);
2278                 }
2279
2280                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2281                 {
2282                         Check.FirstAndSecond (first, second);
2283
2284                         if (comparer == null)
2285                                 comparer = EqualityComparer<TSource>.Default;
2286
2287                         return CreateUnionIterator (first, second, comparer);
2288                 }
2289
2290                 static IEnumerable<TSource> CreateUnionIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2291                 {
2292                         var items = new HashSet<TSource> (comparer);
2293                         foreach (var element in first) {
2294                                 if (! items.Contains (element)) {
2295                                         items.Add (element);
2296                                         yield return element;
2297                                 }
2298                         }
2299
2300                         foreach (var element in second) {
2301                                 if (! items.Contains (element, comparer)) {
2302                                         items.Add (element);
2303                                         yield return element;
2304                                 }
2305                         }
2306                 }
2307
2308                 #endregion
2309
2310                 #region Where
2311
2312                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2313                 {
2314                         Check.SourceAndPredicate (source, predicate);
2315
2316                         return CreateWhereIterator (source, predicate);
2317                 }
2318
2319                 static IEnumerable<TSource> CreateWhereIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
2320                 {
2321                         foreach (TSource element in source)
2322                                 if (predicate (element))
2323                                         yield return element;
2324                 }
2325
2326                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2327                 {
2328                         Check.SourceAndPredicate (source, predicate);
2329
2330                         return CreateWhereIterator (source, predicate);
2331                 }
2332
2333                 static IEnumerable<TSource> CreateWhereIterator<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2334                 {
2335                         int counter = 0;
2336                         foreach (TSource element in source) {
2337                                 if (predicate (element, counter))
2338                                         yield return element;
2339                                 counter++;
2340                         }
2341                 }
2342
2343                 #endregion
2344
2345                 class ReadOnlyCollectionOf<T> {
2346                         public static readonly ReadOnlyCollection<T> Empty = new ReadOnlyCollection<T> (new T [0]);
2347                 }
2348
2349                 internal static ReadOnlyCollection<TSource> ToReadOnlyCollection<TSource> (this IEnumerable<TSource> source)
2350                 {
2351                         if (source == null)
2352                                 return ReadOnlyCollectionOf<TSource>.Empty;
2353
2354                         var ro = source as ReadOnlyCollection<TSource>;
2355                         if (ro != null)
2356                                 return ro;
2357
2358                         return new ReadOnlyCollection<TSource> (source.ToArray<TSource> ());
2359                 }
2360         }
2361 }