2009-03-28 Jb Evain <jbevain@novell.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.Remove (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, (a, b) => Math.Max (a, b));
1056                 }
1057
1058                 public static long? Max (this IEnumerable<long?> source)
1059                 {
1060                         Check.Source (source);
1061
1062                         return IterateNullable (source, (a, b) => Math.Max (a, b));
1063                 }
1064
1065                 public static double? Max (this IEnumerable<double?> source)
1066                 {
1067                         Check.Source (source);
1068
1069                         return IterateNullable (source, (a, b) => Math.Max (a, b));
1070                 }
1071
1072                 public static float? Max (this IEnumerable<float?> source)
1073                 {
1074                         Check.Source (source);
1075
1076                         return IterateNullable (source, (a, b) => Math.Max (a, b));
1077                 }
1078
1079                 public static decimal? Max (this IEnumerable<decimal?> source)
1080                 {
1081                         Check.Source (source);
1082
1083                         return IterateNullable (source, (a, b) => Math.Max (a, b));
1084                 }
1085
1086                 static T? IterateNullable<T> (IEnumerable<T?> source, Func<T, T, T> selector) where T : struct
1087                 {
1088                         bool empty = true;
1089                         T? value = null;
1090                         foreach (var element in source) {
1091                                 if (!element.HasValue)
1092                                         continue;
1093
1094                                 if (!value.HasValue)
1095                                         value = element.Value;
1096                                 else
1097                                         value = selector (element.Value, value.Value);
1098
1099                                 empty = false;
1100                         }
1101
1102                         if (empty)
1103                                 return null;
1104
1105                         return value;
1106                 }
1107
1108                 static TRet? IterateNullable<TSource, TRet> (
1109                         IEnumerable<TSource> source,
1110                         Func<TSource, TRet?> source_selector,
1111                         Func<TRet?, TRet?, bool> selector) where TRet : struct
1112                 {
1113                         bool empty = true;
1114                         TRet? value = null;
1115                         foreach (var element in source) {
1116                                 TRet? item = source_selector (element);
1117
1118                                 if (!value.HasValue)
1119                                         value = item;
1120                                 else if (selector (item, value))
1121                                         value = item;
1122
1123                                 empty = false;
1124                         }
1125
1126                         if (empty)
1127                                 return null;
1128
1129                         return value;
1130                 }
1131
1132                 public static TSource Max<TSource> (this IEnumerable<TSource> source)
1133                 {
1134                         Check.Source (source);
1135
1136                         bool notAssigned = true;
1137                         TSource maximum = default (TSource);
1138                         int counter = 0;
1139                         foreach (TSource element in source) {
1140                                 if (notAssigned) {
1141                                         maximum = element;
1142                                         notAssigned = false;
1143                                 } else {
1144                                         int comparison;
1145                                         if (element is IComparable<TSource>)
1146                                                 comparison = ((IComparable<TSource>) element).CompareTo (maximum);
1147                                         else if (element is System.IComparable)
1148                                                 comparison = ((System.IComparable) element).CompareTo (maximum);
1149                                         else
1150                                                 throw new ArgumentNullException ();
1151
1152                                         if (comparison > 0)
1153                                                 maximum = element;
1154                                 }
1155                                 counter++;
1156                         }
1157
1158                         if (counter == 0)
1159                                 throw new InvalidOperationException ();
1160                         else
1161                                 return maximum;
1162                 }
1163
1164                 public static int Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1165                 {
1166                         Check.SourceAndSelector (source, selector);
1167
1168                         return Iterate (source, int.MinValue, (a, b) => Math.Max (selector (a), b));
1169                 }
1170
1171                 public static long Max<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1172                 {
1173                         Check.SourceAndSelector (source, selector);
1174
1175                         return Iterate (source, long.MinValue, (a, b) => Math.Max (selector (a), b));
1176                 }
1177
1178                 public static double Max<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1179                 {
1180                         Check.SourceAndSelector (source, selector);
1181
1182                         return Iterate (source, double.MinValue, (a, b) => Math.Max (selector (a), b));
1183                 }
1184
1185                 public static float Max<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1186                 {
1187                         Check.SourceAndSelector (source, selector);
1188
1189                         return Iterate (source, float.MinValue, (a, b) => Math.Max (selector (a), b));
1190                 }
1191
1192                 public static decimal Max<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1193                 {
1194                         Check.SourceAndSelector (source, selector);
1195
1196                         return Iterate (source, decimal.MinValue, (a, b) => Math.Max (selector (a), b));
1197                 }
1198
1199                 static U Iterate<T, U> (IEnumerable<T> source, U initValue, Func<T, U, U> selector)
1200                 {
1201                         bool empty = true;
1202                         foreach (var element in source) {
1203                                 initValue = selector (element, initValue);
1204                                 empty = false;
1205                         }
1206
1207                         if (empty)
1208                                 throw new InvalidOperationException ();
1209
1210                         return initValue;
1211                 }
1212
1213                 public static int? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1214                 {
1215                         Check.SourceAndSelector (source, selector);
1216
1217                         return IterateNullable (source, selector, (a, b) => a > b);
1218                 }
1219
1220                 public static long? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1221                 {
1222                         Check.SourceAndSelector (source, selector);
1223
1224                         return IterateNullable (source, selector, (a, b) => a > b);
1225                 }
1226
1227                 public static double? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1228                 {
1229                         Check.SourceAndSelector (source, selector);
1230
1231                         return IterateNullable (source, selector, (a, b) => a > b);
1232                 }
1233
1234                 public static float? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1235                 {
1236                         Check.SourceAndSelector (source, selector);
1237
1238                         return IterateNullable (source, selector, (a, b) => a > b);
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, selector, (a, b) => a > b);
1246                 }
1247
1248                 public static TResult Max<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1249                 {
1250                         Check.SourceAndSelector (source, selector);
1251
1252                         bool notAssigned = true;
1253                         TResult maximum = default (TResult);
1254                         int counter = 0;
1255                         foreach (TSource item in source) {
1256                                 TResult element = selector (item);
1257                                 if (notAssigned) {
1258                                         maximum = element;
1259                                         notAssigned = false;
1260                                 } else {
1261                                         int comparison;
1262                                         if (element is IComparable<TResult>)
1263                                                 comparison = ((IComparable<TResult>) element).CompareTo (maximum);
1264                                         else if (element is System.IComparable)
1265                                                 comparison = ((System.IComparable) element).CompareTo (maximum);
1266                                         else
1267                                                 throw new ArgumentNullException ();
1268
1269                                         if (comparison > 0)
1270                                                 maximum = element;
1271                                 }
1272                                 counter++;
1273                         }
1274
1275                         if (counter == 0)
1276                                 throw new InvalidOperationException ();
1277                         else
1278                                 return maximum;
1279                 }
1280
1281                 #endregion
1282
1283                 #region Min
1284
1285                 public static int Min (this IEnumerable<int> source)
1286                 {
1287                         Check.Source (source);
1288
1289                         return Iterate (source, int.MaxValue, (a, b) => Math.Min (a, b));
1290                 }
1291
1292                 public static long Min (this IEnumerable<long> source)
1293                 {
1294                         Check.Source (source);
1295
1296                         return Iterate (source, long.MaxValue, (a, b) => Math.Min (a, b));
1297                 }
1298
1299                 public static double Min (this IEnumerable<double> source)
1300                 {
1301                         Check.Source (source);
1302
1303                         return Iterate (source, double.MaxValue, (a, b) => Math.Min (a, b));
1304                 }
1305
1306                 public static float Min (this IEnumerable<float> source)
1307                 {
1308                         Check.Source (source);
1309
1310                         return Iterate (source, float.MaxValue, (a, b) => Math.Min (a, b));
1311                 }
1312
1313                 public static decimal Min (this IEnumerable<decimal> source)
1314                 {
1315                         Check.Source (source);
1316
1317                         return Iterate (source, decimal.MaxValue, (a, b) => Math.Min (a, b));
1318                 }
1319
1320                 public static int? Min (this IEnumerable<int?> source)
1321                 {
1322                         Check.Source (source);
1323
1324                         return IterateNullable (source, (a, b) => Math.Min (a, b));
1325                 }
1326
1327                 public static long? Min (this IEnumerable<long?> source)
1328                 {
1329                         Check.Source (source);
1330
1331                         return IterateNullable (source, (a, b) => Math.Min (a, b));
1332                 }
1333
1334                 public static double? Min (this IEnumerable<double?> source)
1335                 {
1336                         Check.Source (source);
1337
1338                         return IterateNullable (source, (a, b) => Math.Min (a, b));
1339                 }
1340
1341                 public static float? Min (this IEnumerable<float?> source)
1342                 {
1343                         Check.Source (source);
1344
1345                         return IterateNullable (source, (a, b) => Math.Min (a, b));
1346                 }
1347
1348                 public static decimal? Min (this IEnumerable<decimal?> source)
1349                 {
1350                         Check.Source (source);
1351
1352                         return IterateNullable (source, (a, b) => Math.Min (a, b));
1353                 }
1354
1355                 public static TSource Min<TSource> (this IEnumerable<TSource> source)
1356                 {
1357                         Check.Source (source);
1358
1359                         bool notAssigned = true;
1360                         TSource minimum = default (TSource);
1361                         int counter = 0;
1362                         foreach (TSource element in source) {
1363                                 if (notAssigned) {
1364                                         minimum = element;
1365                                         notAssigned = false;
1366                                 } else {
1367                                         int comparison;
1368                                         if (element is IComparable<TSource>)
1369                                                 comparison = ((IComparable<TSource>) element).CompareTo (minimum);
1370                                         else if (element is System.IComparable)
1371                                                 comparison = ((System.IComparable) element).CompareTo (minimum);
1372                                         else
1373                                                 throw new ArgumentNullException ();
1374
1375                                         if (comparison < 0)
1376                                                 minimum = element;
1377                                 }
1378                                 counter++;
1379                         }
1380
1381                         if (counter == 0)
1382                                 throw new InvalidOperationException ();
1383                         else
1384                                 return minimum;
1385                 }
1386
1387                 public static int Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1388                 {
1389                         Check.SourceAndSelector (source, selector);
1390
1391                         return Iterate (source, int.MaxValue, (a, b) => Math.Min (selector (a), b));
1392                 }
1393
1394                 public static long Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1395                 {
1396                         Check.SourceAndSelector (source, selector);
1397
1398                         return Iterate (source, long.MaxValue, (a, b) => Math.Min (selector (a), b));
1399                 }
1400
1401                 public static double Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1402                 {
1403                         Check.SourceAndSelector (source, selector);
1404
1405                         return Iterate (source, double.MaxValue, (a, b) => Math.Min (selector (a), b));
1406                 }
1407
1408                 public static float Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1409                 {
1410                         Check.SourceAndSelector (source, selector);
1411
1412                         return Iterate (source, float.MaxValue, (a, b) => Math.Min (selector (a), b));
1413                 }
1414
1415                 public static decimal Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1416                 {
1417                         Check.SourceAndSelector (source, selector);
1418
1419                         return Iterate (source, decimal.MaxValue, (a, b) => Math.Min (selector (a), b));
1420                 }
1421
1422                 public static int? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1423                 {
1424                         Check.SourceAndSelector (source, selector);
1425
1426                         return IterateNullable (source, selector, (a, b) => a < b);
1427                 }
1428
1429                 public static long? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1430                 {
1431                         Check.SourceAndSelector (source, selector);
1432
1433                         return IterateNullable (source, selector, (a, b) => a < b);
1434                 }
1435
1436                 public static float? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1437                 {
1438                         Check.SourceAndSelector (source, selector);
1439
1440                         return IterateNullable (source, selector, (a, b) => a < b);
1441                 }
1442
1443                 public static double? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1444                 {
1445                         Check.SourceAndSelector (source, selector);
1446
1447                         return IterateNullable (source, selector, (a, b) => a < b);
1448                 }
1449
1450                 public static decimal? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1451                 {
1452                         Check.SourceAndSelector (source, selector);
1453
1454                         return IterateNullable (source, selector, (a, b) => a < b);
1455                 }
1456
1457                 public static TResult Min<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1458                 {
1459                         Check.SourceAndSelector (source, selector);
1460
1461                         bool notAssigned = true;
1462                         TResult minimum = default (TResult);
1463                         int counter = 0;
1464                         foreach (TSource item in source) {
1465                                 TResult element = selector (item);
1466                                 if (notAssigned) {
1467                                         minimum = element;
1468                                         notAssigned = false;
1469                                 } else {
1470                                         int comparison;
1471                                         if (element is IComparable<TResult>)
1472                                                 comparison = ((IComparable<TResult>) element).CompareTo (minimum);
1473                                         else if (element is System.IComparable)
1474                                                 comparison = ((System.IComparable) element).CompareTo (minimum);
1475                                         else
1476                                                 throw new ArgumentNullException ();
1477
1478                                         if (comparison < 0)
1479                                                 minimum = element;
1480                                 }
1481                                 counter++;
1482                         }
1483
1484                         if (counter == 0)
1485                                 throw new InvalidOperationException ();
1486                         else
1487                                 return minimum;
1488                 }
1489
1490                 #endregion
1491
1492                 #region OfType
1493
1494                 public static IEnumerable<TResult> OfType<TResult> (this IEnumerable source)
1495                 {
1496                         Check.Source (source);
1497
1498                         return CreateOfTypeIterator<TResult> (source);
1499                 }
1500
1501                 static IEnumerable<TResult> CreateOfTypeIterator<TResult> (IEnumerable source)
1502                 {
1503                         foreach (object element in source)
1504                                 if (element is TResult)
1505                                         yield return (TResult) element;
1506                 }
1507
1508                 #endregion
1509
1510                 #region OrderBy
1511
1512                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
1513                                 Func<TSource, TKey> keySelector)
1514                 {
1515                         return OrderBy<TSource, TKey> (source, keySelector, null);
1516                 }
1517
1518                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
1519                                 Func<TSource, TKey> keySelector,
1520                                 IComparer<TKey> comparer)
1521                 {
1522                         Check.SourceAndKeySelector (source, keySelector);
1523
1524                         return new OrderedSequence<TSource, TKey> (source, keySelector, comparer, SortDirection.Ascending);
1525                 }
1526
1527                 #endregion
1528
1529                 #region OrderByDescending
1530
1531                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
1532                                 Func<TSource, TKey> keySelector)
1533                 {
1534                         return OrderByDescending<TSource, TKey> (source, keySelector, null);
1535                 }
1536
1537                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
1538                                 Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
1539                 {
1540                         Check.SourceAndKeySelector (source, keySelector);
1541
1542                         return new OrderedSequence<TSource, TKey> (source, keySelector, comparer, SortDirection.Descending);
1543                 }
1544
1545                 #endregion
1546
1547                 #region Range
1548
1549                 public static IEnumerable<int> Range (int start, int count)
1550                 {
1551                         if (count < 0)
1552                                 throw new ArgumentOutOfRangeException ("count");
1553
1554                         long upto = ((long) start + count) - 1;
1555
1556                         if (upto > int.MaxValue)
1557                                 throw new ArgumentOutOfRangeException ();
1558
1559                         return CreateRangeIterator (start, (int) upto);
1560                 }
1561
1562                 static IEnumerable<int> CreateRangeIterator (int start, int upto)
1563                 {
1564                         for (int i = start; i <= upto; i++)
1565                                 yield return i;
1566                 }
1567
1568                 #endregion
1569
1570                 #region Repeat
1571
1572                 public static IEnumerable<TResult> Repeat<TResult> (TResult element, int count)
1573                 {
1574                         if (count < 0)
1575                                 throw new ArgumentOutOfRangeException ();
1576
1577                         return CreateRepeatIterator (element, count);
1578                 }
1579
1580                 static IEnumerable<TResult> CreateRepeatIterator<TResult> (TResult element, int count)
1581                 {
1582                         for (int i = 0; i < count; i++)
1583                                 yield return element;
1584                 }
1585
1586                 #endregion
1587
1588                 #region Reverse
1589
1590                 public static IEnumerable<TSource> Reverse<TSource> (this IEnumerable<TSource> source)
1591                 {
1592                         Check.Source (source);
1593
1594                         var list = source as IList<TSource>;
1595                         if (list == null)
1596                                 list = new List<TSource> (source);
1597
1598                         return CreateReverseIterator (list);
1599                 }
1600
1601                 static IEnumerable<TSource> CreateReverseIterator<TSource> (IList<TSource> source)
1602                 {
1603                         for (int i = source.Count; i > 0; --i)
1604                                 yield return source [i - 1];
1605                 }
1606
1607                 #endregion
1608
1609                 #region Select
1610
1611                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1612                 {
1613                         Check.SourceAndSelector (source, selector);
1614
1615                         return CreateSelectIterator (source, selector);
1616                 }
1617
1618                 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, TResult> selector)
1619                 {
1620                         foreach (var element in source)
1621                                 yield return selector (element);
1622                 }
1623
1624                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
1625                 {
1626                         Check.SourceAndSelector (source, selector);
1627
1628                         return CreateSelectIterator (source, selector);
1629                 }
1630
1631                 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
1632                 {
1633                         int counter = 0;
1634                         foreach (TSource element in source) {
1635                                 yield return selector (element, counter);
1636                                 counter++;
1637                         }
1638                 }
1639
1640                 #endregion
1641
1642                 #region SelectMany
1643
1644                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
1645                 {
1646                         Check.SourceAndSelector (source, selector);
1647
1648                         return CreateSelectManyIterator (source, selector);
1649                 }
1650
1651                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
1652                 {
1653                         foreach (TSource element in source)
1654                                 foreach (TResult item in selector (element))
1655                                         yield return item;
1656                 }
1657
1658                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
1659                 {
1660                         Check.SourceAndSelector (source, selector);
1661
1662                         return CreateSelectManyIterator (source, selector);
1663                 }
1664
1665                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
1666                 {
1667                         int counter = 0;
1668                         foreach (TSource element in source) {
1669                                 foreach (TResult item in selector (element, counter))
1670                                         yield return item;
1671                                 counter++;
1672                         }
1673                 }
1674
1675                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
1676                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1677                 {
1678                         Check.SourceAndCollectionSelectors (source, collectionSelector, selector);
1679
1680                         return CreateSelectManyIterator (source, collectionSelector, selector);
1681                 }
1682
1683                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult> (IEnumerable<TSource> source,
1684                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1685                 {
1686                         foreach (TSource element in source)
1687                                 foreach (TCollection collection in collectionSelector (element))
1688                                         yield return selector (element, collection);
1689                 }
1690
1691                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
1692                         Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1693                 {
1694                         Check.SourceAndCollectionSelectors (source, collectionSelector, selector);
1695
1696                         return CreateSelectManyIterator (source, collectionSelector, selector);
1697                 }
1698
1699                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult> (IEnumerable<TSource> source,
1700                         Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1701                 {
1702                         int counter = 0;
1703                         foreach (TSource element in source)
1704                                 foreach (TCollection collection in collectionSelector (element, counter++))
1705                                         yield return selector (element, collection);
1706                 }
1707
1708                 #endregion
1709
1710                 #region Single
1711
1712                 static TSource Single<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate, Fallback fallback)
1713                 {
1714                         var found = false;
1715                         var item = default (TSource);
1716
1717                         foreach (var element in source) {
1718                                 if (!predicate (element))
1719                                         continue;
1720
1721                                 if (found)
1722                                         throw new InvalidOperationException ();
1723
1724                                 found = true;
1725                                 item = element;
1726                         }
1727
1728                         if (!found && fallback == Fallback.Throw)
1729                                 throw new InvalidOperationException ();
1730
1731                         return item;
1732                 }
1733
1734                 public static TSource Single<TSource> (this IEnumerable<TSource> source)
1735                 {
1736                         Check.Source (source);
1737
1738                         return source.Single (PredicateOf<TSource>.Always, Fallback.Throw);
1739                 }
1740
1741                 public static TSource Single<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1742                 {
1743                         Check.SourceAndPredicate (source, predicate);
1744
1745                         return source.Single (predicate, Fallback.Throw);
1746                 }
1747
1748                 #endregion
1749
1750                 #region SingleOrDefault
1751
1752                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source)
1753                 {
1754                         Check.Source (source);
1755
1756                         return source.Single (PredicateOf<TSource>.Always, Fallback.Default);
1757                 }
1758
1759                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1760                 {
1761                         Check.SourceAndPredicate (source, predicate);
1762
1763                         return source.Single (predicate, Fallback.Default);
1764                 }
1765
1766                 #endregion
1767
1768                 #region Skip
1769
1770                 public static IEnumerable<TSource> Skip<TSource> (this IEnumerable<TSource> source, int count)
1771                 {
1772                         Check.Source (source);
1773
1774                         return CreateSkipIterator (source, count);
1775                 }
1776
1777                 static IEnumerable<TSource> CreateSkipIterator<TSource> (IEnumerable<TSource> source, int count)
1778                 {
1779                         int i = 0;
1780                         foreach (var element in source) {
1781                                 if (i++ < count)
1782                                         continue;
1783
1784                                 yield return element;
1785                         }
1786                 }
1787
1788                 #endregion
1789
1790                 #region SkipWhile
1791
1792                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1793                 {
1794                         Check.SourceAndPredicate (source, predicate);
1795
1796                         return CreateSkipWhileIterator (source, predicate);
1797                 }
1798
1799                 static IEnumerable<TSource> CreateSkipWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
1800                 {
1801                         bool yield = false;
1802
1803                         foreach (TSource element in source) {
1804                                 if (yield)
1805                                         yield return element;
1806                                 else
1807                                         if (!predicate (element)) {
1808                                                 yield return element;
1809                                                 yield = true;
1810                                         }
1811                         }
1812                 }
1813
1814                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
1815                 {
1816                         Check.SourceAndPredicate (source, predicate);
1817
1818                         return CreateSkipWhileIterator (source, predicate);
1819                 }
1820
1821                 static IEnumerable<TSource> CreateSkipWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
1822                 {
1823                         int counter = 0;
1824                         bool yield = false;
1825
1826                         foreach (TSource element in source) {
1827                                 if (yield)
1828                                         yield return element;
1829                                 else
1830                                         if (!predicate (element, counter)) {
1831                                                 yield return element;
1832                                                 yield = true;
1833                                         }
1834                                 counter++;
1835                         }
1836                 }
1837
1838                 #endregion
1839
1840                 #region Sum
1841
1842                 public static int Sum (this IEnumerable<int> source)
1843                 {
1844                         Check.Source (source);
1845
1846                         return Sum<int, int> (source, (a, b) => checked (a + b));
1847                 }
1848
1849                 public static int? Sum (this IEnumerable<int?> source)
1850                 {
1851                         Check.Source (source);
1852
1853                         return source.SumNullable<int?, int?> (0, (total, element) => element.HasValue ? checked (total + element) : total);
1854                 }
1855
1856                 public static int Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1857                 {
1858                         Check.SourceAndSelector (source, selector);
1859
1860                         return Sum<TSource, int> (source, (a, b) => checked (a + selector (b)));
1861                 }
1862
1863                 public static int? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1864                 {
1865                         Check.SourceAndSelector (source, selector);
1866
1867                         return source.SumNullable<TSource, int?> (0, (a, b) => {
1868                                 var value = selector (b);
1869                                 return value.HasValue ? checked (a + value.Value) : a;
1870                         });
1871                 }
1872
1873                 public static long Sum (this IEnumerable<long> source)
1874                 {
1875                         Check.Source (source);
1876
1877                         return Sum<long, long> (source, (a, b) => checked (a + b));
1878                 }
1879
1880                 public static long? Sum (this IEnumerable<long?> source)
1881                 {
1882                         Check.Source (source);
1883
1884                         return source.SumNullable<long?, long?> (0, (total, element) => element.HasValue ? checked (total + element) : total);
1885                 }
1886
1887                 public static long Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1888                 {
1889                         Check.SourceAndSelector (source, selector);
1890
1891                         return Sum<TSource, long> (source, (a, b) => checked (a + selector (b)));
1892                 }
1893
1894                 public static long? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1895                 {
1896                         Check.SourceAndSelector (source, selector);
1897
1898                         return source.SumNullable<TSource, long?> (0, (a, b) => {
1899                                 var value = selector (b);
1900                                 return value.HasValue ? checked (a + value.Value) : a;
1901                         });
1902                 }
1903
1904                 public static double Sum (this IEnumerable<double> source)
1905                 {
1906                         Check.Source (source);
1907
1908                         return Sum<double, double> (source, (a, b) => checked (a + b));
1909                 }
1910
1911                 public static double? Sum (this IEnumerable<double?> source)
1912                 {
1913                         Check.Source (source);
1914
1915                         return source.SumNullable<double?, double?> (0, (total, element) => element.HasValue ? checked (total + element) : total);
1916                 }
1917
1918                 public static double Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1919                 {
1920                         Check.SourceAndSelector (source, selector);
1921
1922                         return Sum<TSource, double> (source, (a, b) => checked (a + selector (b)));
1923                 }
1924
1925                 public static double? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1926                 {
1927                         Check.SourceAndSelector (source, selector);
1928
1929                         return source.SumNullable<TSource, double?> (0, (a, b) => {
1930                                 var value = selector (b);
1931                                 return value.HasValue ? checked (a + value.Value) : a;
1932                         });
1933                 }
1934
1935                 public static float Sum (this IEnumerable<float> source)
1936                 {
1937                         Check.Source (source);
1938
1939                         return Sum<float, float> (source, (a, b) => checked (a + b));
1940                 }
1941
1942                 public static float? Sum (this IEnumerable<float?> source)
1943                 {
1944                         Check.Source (source);
1945
1946                         return source.SumNullable<float?, float?> (0, (total, element) => element.HasValue ? checked (total + element) : total);
1947                 }
1948
1949                 public static float Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1950                 {
1951                         Check.SourceAndSelector (source, selector);
1952
1953                         return Sum<TSource, float> (source, (a, b) => checked (a + selector (b)));
1954                 }
1955
1956                 public static float? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1957                 {
1958                         Check.SourceAndSelector (source, selector);
1959
1960                         return source.SumNullable<TSource, float?> (0, (a, b) => {
1961                                 var value = selector (b);
1962                                 return value.HasValue ? checked (a + value.Value) : a;
1963                         });
1964                 }
1965
1966                 public static decimal Sum (this IEnumerable<decimal> source)
1967                 {
1968                         Check.Source (source);
1969
1970                         return Sum<decimal, decimal> (source, (a, b) => checked (a + b));
1971                 }
1972
1973                 public static decimal? Sum (this IEnumerable<decimal?> source)
1974                 {
1975                         Check.Source (source);
1976
1977                         return source.SumNullable<decimal?, decimal?> (0, (total, element) => element.HasValue ? checked (total + element) : total);
1978                 }
1979
1980                 public static decimal Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1981                 {
1982                         Check.SourceAndSelector (source, selector);
1983
1984                         return Sum<TSource, decimal> (source, (a, b) => checked (a + selector (b)));
1985                 }
1986
1987                 public static decimal? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1988                 {
1989                         Check.SourceAndSelector (source, selector);
1990
1991                         return source.SumNullable<TSource, decimal?> (0, (a, b) => {
1992                                 var value = selector (b);
1993                                 return value.HasValue ? checked (a + value.Value) : a;
1994                         });
1995                 }
1996
1997                 static TR Sum<TA, TR> (this IEnumerable<TA> source, Func<TR, TA, TR> selector)
1998                 {
1999                         TR total = default (TR);
2000                         long counter = 0;
2001                         foreach (var element in source) {
2002                                 total = selector (total, element);
2003                                 ++counter;
2004                         }
2005
2006                         return total;
2007                 }
2008
2009                 static TR SumNullable<TA, TR> (this IEnumerable<TA> source, TR zero, Func<TR, TA, TR> selector)
2010                 {
2011                         TR total = zero;
2012                         foreach (var element in source) {
2013                                 total = selector (total, element);
2014                         }
2015
2016                         return total;
2017                 }
2018
2019                 #endregion
2020
2021                 #region Take
2022
2023                 public static IEnumerable<TSource> Take<TSource> (this IEnumerable<TSource> source, int count)
2024                 {
2025                         Check.Source (source);
2026
2027                         return CreateTakeIterator (source, count);
2028                 }
2029
2030                 static IEnumerable<TSource> CreateTakeIterator<TSource> (IEnumerable<TSource> source, int count)
2031                 {
2032                         if (count <= 0)
2033                                 yield break;
2034
2035                         int counter = 0;
2036                         foreach (TSource element in source) {
2037                                 yield return element;
2038
2039                                 if (++counter == count)
2040                                         yield break;
2041                         }
2042                 }
2043
2044                 #endregion
2045
2046                 #region TakeWhile
2047
2048                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2049                 {
2050                         Check.SourceAndPredicate (source, predicate);
2051
2052                         return CreateTakeWhileIterator (source, predicate);
2053                 }
2054
2055                 static IEnumerable<TSource> CreateTakeWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
2056                 {
2057                         foreach (var element in source) {
2058                                 if (!predicate (element))
2059                                         yield break;
2060
2061                                 yield return element;
2062                         }
2063                 }
2064
2065                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2066                 {
2067                         Check.SourceAndPredicate (source, predicate);
2068
2069                         return CreateTakeWhileIterator (source, predicate);
2070                 }
2071
2072                 static IEnumerable<TSource> CreateTakeWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2073                 {
2074                         int counter = 0;
2075                         foreach (var element in source) {
2076                                 if (!predicate (element, counter))
2077                                         yield break;
2078
2079                                 yield return element;
2080                                 counter++;
2081                         }
2082                 }
2083
2084                 #endregion
2085
2086                 #region ThenBy
2087
2088                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2089                 {
2090                         return ThenBy<TSource, TKey> (source, keySelector, null);
2091                 }
2092
2093                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2094                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2095                 {
2096                         Check.SourceAndKeySelector (source, keySelector);
2097
2098                         return source.CreateOrderedEnumerable (keySelector, comparer, false);
2099                 }
2100
2101                 #endregion
2102
2103                 #region ThenByDescending
2104
2105                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2106                         Func<TSource, TKey> keySelector)
2107                 {
2108                         return ThenByDescending<TSource, TKey> (source, keySelector, null);
2109                 }
2110
2111                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2112                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2113                 {
2114                         Check.SourceAndKeySelector (source, keySelector);
2115
2116                         return source.CreateOrderedEnumerable (keySelector, comparer, true);
2117                 }
2118
2119                 #endregion
2120
2121                 #region ToArray
2122
2123                 public static TSource [] ToArray<TSource> (this IEnumerable<TSource> source)
2124                 {
2125                         Check.Source (source);
2126
2127                         var collection = source as ICollection<TSource>;
2128                         if (collection != null) {
2129                                 var array = new TSource [collection.Count];
2130                                 collection.CopyTo (array, 0);
2131                                 return array;
2132                         }
2133
2134                         return new List<TSource> (source).ToArray ();
2135                 }
2136
2137                 #endregion
2138
2139                 #region ToDictionary
2140                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2141                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2142                 {
2143                         return ToDictionary<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2144                 }
2145
2146                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2147                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2148                 {
2149                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2150
2151                         if (comparer == null)
2152                                 comparer = EqualityComparer<TKey>.Default;
2153
2154                         var dict = new Dictionary<TKey, TElement> (comparer);
2155                         foreach (var e in source)
2156                                 dict.Add (keySelector (e), elementSelector (e));
2157
2158                         return dict;
2159                 }
2160
2161                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2162                                 Func<TSource, TKey> keySelector)
2163                 {
2164                         return ToDictionary (source, keySelector, null);
2165                 }
2166
2167                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2168                                 Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2169                 {
2170                         return ToDictionary<TSource, TKey, TSource> (source, keySelector, Function<TSource>.Identity, comparer);
2171                 }
2172
2173                 #endregion
2174
2175                 #region ToList
2176                 public static List<TSource> ToList<TSource> (this IEnumerable<TSource> source)
2177                 {
2178                         Check.Source (source);
2179
2180                         return new List<TSource> (source);
2181                 }
2182                 #endregion
2183
2184                 #region ToLookup
2185
2186                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2187                 {
2188                         return ToLookup<TSource, TKey, TSource> (source, keySelector, Function<TSource>.Identity, null);
2189                 }
2190
2191                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source,
2192                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2193                 {
2194                         return ToLookup<TSource, TKey, TSource> (source, keySelector, element => element, comparer);
2195                 }
2196
2197                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2198                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2199                 {
2200                         return ToLookup<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2201                 }
2202
2203                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2204                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2205                 {
2206                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2207
2208                         var dictionary = new Dictionary<TKey, List<TElement>> (comparer ?? EqualityComparer<TKey>.Default);
2209                         foreach (var element in source) {
2210                                 var key = keySelector (element);
2211                                 if (key == null)
2212                                         throw new ArgumentNullException ("key");
2213
2214                                 List<TElement> list;
2215                                 if (!dictionary.TryGetValue (key, out list)) {
2216                                         list = new List<TElement> ();
2217                                         dictionary.Add (key, list);
2218                                 }
2219
2220                                 list.Add (elementSelector (element));
2221                         }
2222
2223                         return new Lookup<TKey, TElement> (dictionary);
2224                 }
2225
2226                 #endregion
2227
2228                 #region SequenceEqual
2229
2230                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2231                 {
2232                         return first.SequenceEqual (second, null);
2233                 }
2234
2235                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2236                 {
2237                         Check.FirstAndSecond (first, second);
2238
2239                         if (comparer == null)
2240                                 comparer = EqualityComparer<TSource>.Default;
2241
2242                         using (IEnumerator<TSource> first_enumerator = first.GetEnumerator (),
2243                                 second_enumerator = second.GetEnumerator ()) {
2244
2245                                 while (first_enumerator.MoveNext ()) {
2246                                         if (!second_enumerator.MoveNext ())
2247                                                 return false;
2248
2249                                         if (!comparer.Equals (first_enumerator.Current, second_enumerator.Current))
2250                                                 return false;
2251                                 }
2252
2253                                 return !second_enumerator.MoveNext ();
2254                         }
2255                 }
2256
2257                 #endregion
2258
2259                 #region Union
2260
2261                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2262                 {
2263                         Check.FirstAndSecond (first, second);
2264
2265                         return first.Union (second, null);
2266                 }
2267
2268                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2269                 {
2270                         Check.FirstAndSecond (first, second);
2271
2272                         if (comparer == null)
2273                                 comparer = EqualityComparer<TSource>.Default;
2274
2275                         return CreateUnionIterator (first, second, comparer);
2276                 }
2277
2278                 static IEnumerable<TSource> CreateUnionIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2279                 {
2280                         var items = new HashSet<TSource> (comparer);
2281                         foreach (var element in first) {
2282                                 if (! items.Contains (element)) {
2283                                         items.Add (element);
2284                                         yield return element;
2285                                 }
2286                         }
2287
2288                         foreach (var element in second) {
2289                                 if (! items.Contains (element, comparer)) {
2290                                         items.Add (element);
2291                                         yield return element;
2292                                 }
2293                         }
2294                 }
2295
2296                 #endregion
2297
2298                 #region Where
2299
2300                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2301                 {
2302                         Check.SourceAndPredicate (source, predicate);
2303
2304                         return CreateWhereIterator (source, predicate);
2305                 }
2306
2307                 static IEnumerable<TSource> CreateWhereIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
2308                 {
2309                         foreach (TSource element in source)
2310                                 if (predicate (element))
2311                                         yield return element;
2312                 }
2313
2314                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2315                 {
2316                         Check.SourceAndPredicate (source, predicate);
2317
2318                         return CreateWhereIterator (source, predicate);
2319                 }
2320
2321                 static IEnumerable<TSource> CreateWhereIterator<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2322                 {
2323                         int counter = 0;
2324                         foreach (TSource element in source) {
2325                                 if (predicate (element, counter))
2326                                         yield return element;
2327                                 counter++;
2328                         }
2329                 }
2330
2331                 #endregion
2332
2333                 class ReadOnlyCollectionOf<T> {
2334                         public static readonly ReadOnlyCollection<T> Empty = new ReadOnlyCollection<T> (new T [0]);
2335                 }
2336
2337                 internal static ReadOnlyCollection<TSource> ToReadOnlyCollection<TSource> (this IEnumerable<TSource> source)
2338                 {
2339                         if (source == null)
2340                                 return ReadOnlyCollectionOf<TSource>.Empty;
2341
2342                         var ro = source as ReadOnlyCollection<TSource>;
2343                         if (ro != null)
2344                                 return ro;
2345
2346                         return new ReadOnlyCollection<TSource> (source.ToArray<TSource> ());
2347                 }
2348         }
2349 }