56d52d4f45391875d38289ed1c46b9af57243fd7
[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                 static class PredicateOf<T> {
49                         public static readonly Func<T, bool> Always = (t) => true;
50                 }
51
52                 static class Function<T> {
53                         public static readonly Func<T, T> Identity = (t) => t;
54                 }
55                 
56                 static class EmptyOf<T> {
57                         public static readonly T[] Instance = new T [0];
58                 }
59                 
60                 static class ReadOnlyCollectionOf<T> {
61                         public static readonly ReadOnlyCollection<T> Empty = new ReadOnlyCollection<T> (EmptyOf<T>.Instance);
62                 }
63
64                 #region Aggregate
65
66                 public static TSource Aggregate<TSource> (this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func)
67                 {
68                         Check.SourceAndFunc (source, func);
69
70                         // custom foreach so that we can efficiently throw an exception
71                         // if zero elements and treat the first element differently
72                         using (var enumerator = source.GetEnumerator ()) {
73                                 if (!enumerator.MoveNext ())
74                                         throw new InvalidOperationException ("No elements in source list");
75
76                                 TSource folded = enumerator.Current;
77                                 while (enumerator.MoveNext ())
78                                         folded = func (folded, enumerator.Current);
79                                 return folded;
80                         }
81                 }
82
83                 public static TAccumulate Aggregate<TSource, TAccumulate> (this IEnumerable<TSource> source,
84                         TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func)
85                 {
86                         Check.SourceAndFunc (source, func);
87
88                         TAccumulate folded = seed;
89                         foreach (TSource element in source)
90                                 folded = func (folded, element);
91
92                         return folded;
93                 }
94
95                 public static TResult Aggregate<TSource, TAccumulate, TResult> (this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector)
96                 {
97                         Check.SourceAndFunc (source, func);
98                         if (resultSelector == null)
99                                 throw new ArgumentNullException ("resultSelector");
100
101                         var result = seed;
102                         foreach (var e in source)
103                                 result = func (result, e);
104
105                         return resultSelector (result);
106                 }
107
108                 #endregion
109
110                 #region All
111
112                 public static bool All<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
113                 {
114                         Check.SourceAndPredicate (source, predicate);
115
116                         foreach (var element in source)
117                                 if (!predicate (element))
118                                         return false;
119
120                         return true;
121                 }
122
123                 #endregion
124
125                 #region Any
126
127                 public static bool Any<TSource> (this IEnumerable<TSource> source)
128                 {
129                         Check.Source (source);
130
131                         var collection = source as ICollection<TSource>;
132                         if (collection != null)
133                                 return collection.Count > 0;
134
135                         using (var enumerator = source.GetEnumerator ())
136                                 return enumerator.MoveNext ();
137                 }
138
139                 public static bool Any<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
140                 {
141                         Check.SourceAndPredicate (source, predicate);
142
143                         foreach (TSource element in source)
144                                 if (predicate (element))
145                                         return true;
146
147                         return false;
148                 }
149
150                 #endregion
151
152                 #region AsEnumerable
153
154                 public static IEnumerable<TSource> AsEnumerable<TSource> (this IEnumerable<TSource> source)
155                 {
156                         return source;
157                 }
158
159                 #endregion
160
161                 #region Average
162
163                 public static double Average (this IEnumerable<int> source)
164                 {
165                         Check.Source (source);
166
167                         long total = 0;
168                         int count = 0;
169                         foreach (var element in source){
170                                 total = checked (total + element);
171                                 count++;
172                         }
173                         if (count == 0)
174                                 throw new InvalidOperationException ();
175                         return total / (double) count;
176                 }
177
178                 public static double Average (this IEnumerable<long> source)
179                 {
180                         Check.Source (source);
181
182                         long total = 0;
183                         long count = 0;
184                         foreach (var element in source){
185                                 total += element;
186                                 count++;
187                         }
188                         if (count == 0)
189                                 throw new InvalidOperationException ();
190                         return total / (double) count;
191                 }
192
193                 public static double Average (this IEnumerable<double> source)
194                 {
195                         Check.Source (source);
196
197                         double total = 0;
198                         long count = 0;
199                         foreach (var element in source){
200                                 total += element;
201                                 count++;
202                         }
203                         if (count == 0)
204                                 throw new InvalidOperationException ();
205                         return total / count;
206                 }
207
208                 public static float Average (this IEnumerable<float> source)
209                 {
210                         Check.Source (source);
211
212                         float total = 0;
213                         long count = 0;
214                         foreach (var element in source){
215                                 total += element;
216                                 count++;
217                         }
218                         if (count == 0)
219                                 throw new InvalidOperationException ();
220                         return total / count;
221                 }
222
223                 public static decimal Average (this IEnumerable<decimal> source)
224                 {
225                         Check.Source (source);
226
227                         decimal total = 0;
228                         long count = 0;
229                         foreach (var element in source){
230                                 total += element;
231                                 count++;
232                         }
233                         if (count == 0)
234                                 throw new InvalidOperationException ();
235                         return total / count;
236                 }
237
238                 static TResult? AverageNullable<TElement, TAggregate, TResult> (this IEnumerable<TElement?> source,
239                         Func<TAggregate, TElement, TAggregate> func, Func<TAggregate, long, TResult> result)
240                         where TElement : struct
241                         where TAggregate : struct
242                         where TResult : struct
243                 {
244                         Check.Source (source);
245
246                         var total = default (TAggregate);
247                         long counter = 0;
248                         foreach (var element in source) {
249                                 if (!element.HasValue)
250                                         continue;
251
252                                 total = func (total, element.Value);
253                                 counter++;
254                         }
255
256                         if (counter == 0)
257                                 return null;
258
259                         return new TResult? (result (total, counter));
260                 }
261
262                 public static double? Average (this IEnumerable<int?> source)
263                 {
264                         Check.Source (source);
265
266                         long total = 0;
267                         long counter = 0;
268                         
269                         foreach (var element in source) {
270                                 if (!element.HasValue)
271                                         continue;
272
273                                 total = total + element.Value;
274                                 counter++;
275                         }
276
277                         if (counter == 0)
278                                 return null;
279
280                         return new double? (total / (double) counter);
281                 }
282
283                 public static double? Average (this IEnumerable<long?> source)
284                 {
285                         Check.Source (source);
286
287                         long total = 0;
288                         long counter = 0;
289                         
290                         foreach (var element in source) {
291                                 if (!element.HasValue)
292                                         continue;
293
294                                 total = checked (total + element.Value);
295                                 counter++;
296                         }
297
298                         if (counter == 0)
299                                 return null;
300
301                         return new double? (total / (double) counter);
302
303                 }
304
305                 public static double? Average (this IEnumerable<double?> source)
306                 {
307                         Check.Source (source);
308
309                         double total = 0;
310                         long counter = 0;
311                         
312                         foreach (var element in source) {
313                                 if (!element.HasValue)
314                                         continue;
315
316                                 total = total + element.Value;
317                                 counter++;
318                         }
319
320                         if (counter == 0)
321                                 return null;
322
323                         return new double? (total / counter);
324
325                 }
326
327                 public static decimal? Average (this IEnumerable<decimal?> source)
328                 {
329                         Check.Source (source);
330
331                         decimal total = 0;
332                         long counter = 0;
333                         
334                         foreach (var element in source) {
335                                 if (!element.HasValue)
336                                         continue;
337
338                                 total = total + element.Value;
339                                 counter++;
340                         }
341
342                         if (counter == 0)
343                                 return null;
344
345                         return new decimal? (total / counter);
346
347                 }
348
349                 public static float? Average (this IEnumerable<float?> source)
350                 {
351                         Check.Source (source);
352
353                         float total = 0;
354                         long counter = 0;
355                         
356                         foreach (var element in source) {
357                                 if (!element.HasValue)
358                                         continue;
359
360                                 total = total + element.Value;
361                                 counter++;
362                         }
363
364                         if (counter == 0)
365                                 return null;
366
367                         return new float? (total / counter);
368
369                 }
370
371                 public static double Average<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
372                 {
373                         Check.SourceAndSelector (source, selector);
374
375                         long total = 0;
376                         long count = 0;
377                         foreach (var element in source){
378                                 total += selector (element);
379                                 count++;
380                         }
381                         if (count == 0)
382                                 throw new InvalidOperationException ();
383                         return total / (double) count;
384                 }
385
386                 public static double? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
387                 {
388                         Check.SourceAndSelector (source, selector);
389
390                         long total = 0;
391                         long counter = 0;
392                         
393                         foreach (var element in source) {
394                                 var value = selector (element);
395                                 if (!value.HasValue)
396                                         continue;
397
398                                 total = total + value.Value;
399                                 counter++;
400                         }
401
402                         if (counter == 0)
403                                 return null;
404
405                         return new double? (total / (double) counter);
406                 }
407
408                 public static double Average<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
409                 {
410                         Check.SourceAndSelector (source, selector);
411
412                         long total = 0;
413                         long count = 0;
414                         foreach (var element in source){
415                                 total = checked (total + selector (element));
416                                 count++;
417                         }
418                         if (count == 0)
419                                 throw new InvalidOperationException ();
420                         return total / (double) count;
421
422                 }
423
424                 public static double? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
425                 {
426                         Check.SourceAndSelector (source, selector);
427
428                         long total = 0;
429                         long counter = 0;
430                         
431                         foreach (var element in source) {
432                                 var value = selector (element);
433                                 if (!value.HasValue)
434                                         continue;
435
436                                 total = checked (total + value.Value);
437                                 counter++;
438                         }
439
440                         if (counter == 0)
441                                 return null;
442
443                         return new double? (total / (double) counter);
444                 }
445
446                 public static double Average<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
447                 {
448                         Check.SourceAndSelector (source, selector);
449
450                         double total = 0;
451                         long count = 0;
452                         foreach (var element in source){
453                                 total += selector (element);
454                                 count++;
455                         }
456                         if (count == 0)
457                                 throw new InvalidOperationException ();
458                         return total / count;
459
460                 }
461
462                 public static double? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
463                 {
464                         Check.SourceAndSelector (source, selector);
465
466                         double total = 0;
467                         long counter = 0;
468                         
469                         foreach (var element in source) {
470                                 var value = selector (element);
471                                 if (!value.HasValue)
472                                         continue;
473
474                                 total = total + value.Value;
475                                 counter++;
476                         }
477
478                         if (counter == 0)
479                                 return null;
480
481                         return new double? (total / counter);
482
483                 }
484
485                 public static float Average<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
486                 {
487                         Check.SourceAndSelector (source, selector);
488
489                         float total = 0;
490                         long count = 0;
491                         foreach (var element in source){
492                                 total += selector (element);
493                                 count++;
494                         }
495                         if (count == 0)
496                                 throw new InvalidOperationException ();
497                         return total / count;
498                 }
499
500                 public static float? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
501                 {
502                         Check.SourceAndSelector (source, selector);
503
504                         float total = 0;
505                         long counter = 0;
506                         
507                         foreach (var element in source) {
508                                 var value = selector (element);
509                                 if (!value.HasValue)
510                                         continue;
511
512                                 total = total + value.Value;
513                                 counter++;
514                         }
515
516                         if (counter == 0)
517                                 return null;
518
519                         return new float? (total / counter);
520                 }
521
522                 public static decimal Average<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
523                 {
524                         Check.SourceAndSelector (source, selector);
525
526                         decimal total = 0;
527                         long count = 0;
528                         foreach (var element in source){
529                                 total += selector (element);
530                                 count++;
531                         }
532                         if (count == 0)
533                                 throw new InvalidOperationException ();
534                         return total / count;
535                 }
536
537                 public static decimal? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
538                 {
539                         Check.SourceAndSelector (source, selector);
540
541                         decimal total = 0;
542                         long counter = 0;
543                         
544                         foreach (var element in source) {
545                                 var value = selector (element);
546                                 if (!value.HasValue)
547                                         continue;
548
549                                 total = total + value.Value;
550                                 counter++;
551                         }
552
553                         if (counter == 0)
554                                 return null;
555
556                         return new decimal? (total / counter);
557                 }
558
559                 #endregion
560
561                 #region Cast
562
563                 public static IEnumerable<TResult> Cast<TResult> (this IEnumerable source)
564                 {
565                         Check.Source (source);
566
567                         var actual = source as IEnumerable<TResult>;
568                         if (actual != null)
569                                 return actual;
570
571                         return CreateCastIterator<TResult> (source);
572                 }
573
574                 static IEnumerable<TResult> CreateCastIterator<TResult> (IEnumerable source)
575                 {
576                         foreach (TResult element in source)
577                                 yield return element;
578                 }
579
580                 #endregion
581
582                 #region Concat
583
584                 public static IEnumerable<TSource> Concat<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
585                 {
586                         Check.FirstAndSecond (first, second);
587
588                         return CreateConcatIterator (first, second);
589                 }
590
591                 static IEnumerable<TSource> CreateConcatIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second)
592                 {
593                         foreach (TSource element in first)
594                                 yield return element;
595                         foreach (TSource element in second)
596                                 yield return element;
597                 }
598
599                 #endregion
600
601                 #region Contains
602
603                 public static bool Contains<TSource> (this IEnumerable<TSource> source, TSource value)
604                 {
605                         var collection = source as ICollection<TSource>;
606                         if (collection != null)
607                                 return collection.Contains (value);
608
609                         return Contains<TSource> (source, value, null);
610                 }
611
612                 public static bool Contains<TSource> (this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
613                 {
614                         Check.Source (source);
615
616                         if (comparer == null)
617                                 comparer = EqualityComparer<TSource>.Default;
618
619                         foreach (var element in source)
620                                 if (comparer.Equals (element, value))
621                                         return true;
622
623                         return false;
624                 }
625                 #endregion
626
627                 #region Count
628
629                 public static int Count<TSource> (this IEnumerable<TSource> source)
630                 {
631                         Check.Source (source);
632
633                         var collection = source as ICollection<TSource>;
634                         if (collection != null)
635                                 return collection.Count;
636
637                         int counter = 0;
638                         using (var enumerator = source.GetEnumerator ())
639                                 while (enumerator.MoveNext ())
640                                         counter++;
641
642                         return counter;
643                 }
644
645                 public static int Count<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
646                 {
647                         Check.SourceAndSelector (source, predicate);
648
649                         int counter = 0;
650                         foreach (var element in source)
651                                 if (predicate (element))
652                                         counter++;
653
654                         return counter;
655                 }
656
657                 #endregion
658
659                 #region DefaultIfEmpty
660
661                 public static IEnumerable<TSource> DefaultIfEmpty<TSource> (this IEnumerable<TSource> source)
662                 {
663                         return DefaultIfEmpty (source, default (TSource));
664                 }
665
666                 public static IEnumerable<TSource> DefaultIfEmpty<TSource> (this IEnumerable<TSource> source, TSource defaultValue)
667                 {
668                         Check.Source (source);
669
670                         return CreateDefaultIfEmptyIterator (source, defaultValue);
671                 }
672
673                 static IEnumerable<TSource> CreateDefaultIfEmptyIterator<TSource> (IEnumerable<TSource> source, TSource defaultValue)
674                 {
675                         bool empty = true;
676                         foreach (TSource item in source) {
677                                 empty = false;
678                                 yield return item;
679                         }
680
681                         if (empty)
682                                 yield return defaultValue;
683                 }
684
685                 #endregion
686
687                 #region Distinct
688
689                 public static IEnumerable<TSource> Distinct<TSource> (this IEnumerable<TSource> source)
690                 {
691                         return Distinct<TSource> (source, null);
692                 }
693
694                 public static IEnumerable<TSource> Distinct<TSource> (this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
695                 {
696                         Check.Source (source);
697
698                         if (comparer == null)
699                                 comparer = EqualityComparer<TSource>.Default;
700
701                         return CreateDistinctIterator (source, comparer);
702                 }
703
704                 static IEnumerable<TSource> CreateDistinctIterator<TSource> (IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
705                 {
706                         var items = new HashSet<TSource> (comparer);
707                         foreach (var element in source) {
708                                 if (! items.Contains (element)) {
709                                         items.Add (element);
710                                         yield return element;
711                                 }
712                         }
713                 }
714
715                 #endregion
716
717                 #region ElementAt
718
719                 static TSource ElementAt<TSource> (this IEnumerable<TSource> source, int index, Fallback fallback)
720                 {
721                         long counter = 0L;
722
723                         foreach (var element in source) {
724                                 if (index == counter++)
725                                         return element;
726                         }
727
728                         if (fallback == Fallback.Throw)
729                                 throw new ArgumentOutOfRangeException ();
730
731                         return default (TSource);
732                 }
733
734                 public static TSource ElementAt<TSource> (this IEnumerable<TSource> source, int index)
735                 {
736                         Check.Source (source);
737
738                         if (index < 0)
739                                 throw new ArgumentOutOfRangeException ();
740
741                         var list = source as IList<TSource>;
742                         if (list != null)
743                                 return list [index];
744
745                         return source.ElementAt (index, Fallback.Throw);
746                 }
747
748                 #endregion
749
750                 #region ElementAtOrDefault
751
752                 public static TSource ElementAtOrDefault<TSource> (this IEnumerable<TSource> source, int index)
753                 {
754                         Check.Source (source);
755
756                         if (index < 0)
757                                 return default (TSource);
758
759                         var list = source as IList<TSource>;
760                         if (list != null)
761                                 return index < list.Count ? list [index] : default (TSource);
762
763                         return source.ElementAt (index, Fallback.Default);
764                 }
765
766                 #endregion
767
768                 #region Empty
769
770                 public static IEnumerable<TResult> Empty<TResult> ()
771                 {
772                         return EmptyOf<TResult>.Instance;
773                 }
774
775                 #endregion
776
777                 #region Except
778
779                 public static IEnumerable<TSource> Except<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
780                 {
781                         return Except (first, second, null);
782                 }
783
784                 public static IEnumerable<TSource> Except<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
785                 {
786                         Check.FirstAndSecond (first, second);
787
788                         if (comparer == null)
789                                 comparer = EqualityComparer<TSource>.Default;
790
791                         return CreateExceptIterator (first, second, comparer);
792                 }
793
794                 static IEnumerable<TSource> CreateExceptIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
795                 {
796                         var items = new HashSet<TSource> (second, comparer);
797                         foreach (var element in first) {
798                                 if (items.Add (element))
799                                         yield return element;
800                         }
801                 }
802
803                 #endregion
804
805                 #region First
806
807                 static TSource First<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate, Fallback fallback)
808                 {
809                         foreach (var element in source)
810                                 if (predicate (element))
811                                         return element;
812
813                         if (fallback == Fallback.Throw)
814                                 throw new InvalidOperationException ();
815
816                         return default (TSource);
817                 }
818
819                 public static TSource First<TSource> (this IEnumerable<TSource> source)
820                 {
821                         Check.Source (source);
822
823                         var list = source as IList<TSource>;
824                         if (list != null) {
825                                 if (list.Count != 0)
826                                         return list [0];
827                         } else {
828                                 using (var enumerator = source.GetEnumerator ()) {
829                                         if (enumerator.MoveNext ())
830                                                 return enumerator.Current;
831                                 }
832                         }
833
834                         throw new InvalidOperationException ("The source sequence is empty");
835                 }
836
837                 public static TSource First<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
838                 {
839                         Check.SourceAndPredicate (source, predicate);
840
841                         return source.First (predicate, Fallback.Throw);
842                 }
843
844                 #endregion
845
846                 #region FirstOrDefault
847
848                 public static TSource FirstOrDefault<TSource> (this IEnumerable<TSource> source)
849                 {
850                         Check.Source (source);
851
852                         return source.First (PredicateOf<TSource>.Always, Fallback.Default);
853                 }
854
855                 public static TSource FirstOrDefault<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
856                 {
857                         Check.SourceAndPredicate (source, predicate);
858
859                         return source.First (predicate, Fallback.Default);
860                 }
861
862                 #endregion
863
864                 #region GroupBy
865
866                 private static List<T> ContainsGroup<K, T> (
867                                 Dictionary<K, List<T>> items, K key, IEqualityComparer<K> comparer)
868                 {
869                         IEqualityComparer<K> comparerInUse = (comparer ?? EqualityComparer<K>.Default);
870                         foreach (KeyValuePair<K, List<T>> value in items) {
871                                 if (comparerInUse.Equals (value.Key, key))
872                                         return value.Value;
873                         }
874                         return null;
875                 }
876
877                 public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this IEnumerable<TSource> source,
878                         Func<TSource, TKey> keySelector)
879                 {
880                         return GroupBy<TSource, TKey> (source, keySelector, null);
881                 }
882
883                 public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this IEnumerable<TSource> source,
884                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
885                 {
886                         Check.SourceAndKeySelector (source, keySelector);
887
888                         return CreateGroupByIterator (source, keySelector, comparer);
889                 }
890
891                 static IEnumerable<IGrouping<TKey, TSource>> CreateGroupByIterator<TSource, TKey> (this IEnumerable<TSource> source,
892                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
893                 {
894                         var groups = new Dictionary<TKey, List<TSource>> ();
895                         var nullList = new List<TSource> ();
896                         int counter = 0;
897                         int nullCounter = -1;
898
899                         foreach (TSource element in source) {
900                                 TKey key = keySelector (element);
901                                 if (key == null) {
902                                         nullList.Add (element);
903                                         if (nullCounter == -1) {
904                                                 nullCounter = counter;
905                                                 counter++;
906                                         }
907                                 } else {
908                                         List<TSource> group = ContainsGroup<TKey, TSource> (groups, key, comparer);
909                                         if (group == null) {
910                                                 group = new List<TSource> ();
911                                                 groups.Add (key, group);
912                                                 counter++;
913                                         }
914                                         group.Add (element);
915                                 }
916                         }
917
918                         counter = 0;
919                         foreach (var group in groups) {
920                                 if (counter == nullCounter) {
921                                         yield return new Grouping<TKey, TSource> (default (TKey), nullList);
922                                         counter++;
923                                 }
924
925                                 yield return new Grouping<TKey, TSource> (group.Key, group.Value);
926                                 counter++;
927                         }
928
929                         if (counter == nullCounter) {
930                                 yield return new Grouping<TKey, TSource> (default (TKey), nullList);
931                                 counter++;
932                         }
933                 }
934
935                 public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this IEnumerable<TSource> source,
936                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
937                 {
938                         return GroupBy<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
939                 }
940
941                 public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this IEnumerable<TSource> source,
942                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
943                 {
944                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
945
946                         return CreateGroupByIterator (source, keySelector, elementSelector, comparer);
947                 }
948
949                 static IEnumerable<IGrouping<TKey, TElement>> CreateGroupByIterator<TSource, TKey, TElement> (this IEnumerable<TSource> source,
950                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
951                 {
952                         var groups = new Dictionary<TKey, List<TElement>> ();
953                         var nullList = new List<TElement> ();
954                         int counter = 0;
955                         int nullCounter = -1;
956
957                         foreach (TSource item in source) {
958                                 TKey key = keySelector (item);
959                                 TElement element = elementSelector (item);
960                                 if (key == null) {
961                                         nullList.Add (element);
962                                         if (nullCounter == -1) {
963                                                 nullCounter = counter;
964                                                 counter++;
965                                         }
966                                 } else {
967                                         List<TElement> group = ContainsGroup<TKey, TElement> (groups, key, comparer);
968                                         if (group == null) {
969                                                 group = new List<TElement> ();
970                                                 groups.Add (key, group);
971                                                 counter++;
972                                         }
973                                         group.Add (element);
974                                 }
975                         }
976
977                         counter = 0;
978                         foreach (var group in groups) {
979                                 if (counter == nullCounter) {
980                                         yield return new Grouping<TKey, TElement> (default (TKey), nullList);
981                                         counter++;
982                                 }
983
984                                 yield return new Grouping<TKey, TElement> (group.Key, group.Value);
985                                 counter++;
986                         }
987
988                         if (counter == nullCounter) {
989                                 yield return new Grouping<TKey, TElement> (default (TKey), nullList);
990                                 counter++;
991                         }
992                 }
993
994                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult> (this IEnumerable<TSource> source,
995                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector,
996                         Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
997                 {
998                         return GroupBy (source, keySelector, elementSelector, resultSelector, null);
999                 }
1000
1001                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult> (this IEnumerable<TSource> source,
1002                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector,
1003                         Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
1004                         IEqualityComparer<TKey> comparer)
1005                 {
1006                         Check.GroupBySelectors (source, keySelector, elementSelector, resultSelector);
1007
1008                         return CreateGroupByIterator (source, keySelector, elementSelector, resultSelector, comparer);
1009                 }
1010
1011                 static IEnumerable<TResult> CreateGroupByIterator<TSource, TKey, TElement, TResult> (this IEnumerable<TSource> source,
1012                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector,
1013                         Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
1014                         IEqualityComparer<TKey> comparer)
1015                 {
1016                         IEnumerable<IGrouping<TKey, TElement>> groups = GroupBy<TSource, TKey, TElement> (
1017                                 source, keySelector, elementSelector, comparer);
1018
1019                         foreach (IGrouping<TKey, TElement> group in groups)
1020                                 yield return resultSelector (group.Key, group);
1021                 }
1022
1023                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult> (this IEnumerable<TSource> source,
1024                         Func<TSource, TKey> keySelector,
1025                         Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
1026                 {
1027                         return GroupBy (source, keySelector, resultSelector, null);
1028                 }
1029
1030                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult> (this IEnumerable<TSource> source,
1031                         Func<TSource, TKey> keySelector,
1032                         Func<TKey, IEnumerable<TSource>, TResult> resultSelector,
1033                         IEqualityComparer<TKey> comparer)
1034                 {
1035                         Check.SourceAndKeyResultSelectors (source, keySelector, resultSelector);
1036
1037                         return CreateGroupByIterator (source, keySelector, resultSelector, comparer);
1038                 }
1039
1040                 static IEnumerable<TResult> CreateGroupByIterator<TSource, TKey, TResult> (this IEnumerable<TSource> source,
1041                         Func<TSource, TKey> keySelector,
1042                         Func<TKey, IEnumerable<TSource>, TResult> resultSelector,
1043                         IEqualityComparer<TKey> comparer)
1044                 {
1045                         IEnumerable<IGrouping<TKey,TSource>> groups = GroupBy<TSource, TKey> (source, keySelector, comparer);
1046
1047                         foreach (IGrouping<TKey, TSource> group in groups)
1048                                 yield return resultSelector (group.Key, group);
1049                 }
1050
1051                 #endregion
1052
1053                 # region GroupJoin
1054
1055                 public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
1056                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
1057                         Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
1058                 {
1059                         return GroupJoin (outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
1060                 }
1061
1062                 public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
1063                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
1064                         Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
1065                         IEqualityComparer<TKey> comparer)
1066                 {
1067                         Check.JoinSelectors (outer, inner, outerKeySelector, innerKeySelector, resultSelector);
1068
1069                         if (comparer == null)
1070                                 comparer = EqualityComparer<TKey>.Default;
1071
1072                         return CreateGroupJoinIterator (outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
1073                 }
1074
1075                 static IEnumerable<TResult> CreateGroupJoinIterator<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
1076                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
1077                         Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
1078                         IEqualityComparer<TKey> comparer)
1079                 {
1080                         ILookup<TKey, TInner> innerKeys = ToLookup<TInner, TKey> (inner, innerKeySelector, comparer);
1081                         /*Dictionary<K, List<U>> innerKeys = new Dictionary<K, List<U>> ();
1082                         foreach (U element in inner)
1083                         {
1084                                         K innerKey = innerKeySelector (element);
1085                                         if (!innerKeys.ContainsKey (innerKey))
1086                                                         innerKeys.Add (innerKey, new List<U> ());
1087                                         innerKeys[innerKey].Add (element);
1088                         }*/
1089
1090                         foreach (TOuter element in outer) {
1091                                 TKey outerKey = outerKeySelector (element);
1092                                 if (innerKeys.Contains (outerKey))
1093                                         yield return resultSelector (element, innerKeys [outerKey]);
1094                                 else
1095                                         yield return resultSelector (element, Empty<TInner> ());
1096                         }
1097                 }
1098
1099                 #endregion
1100
1101                 #region Intersect
1102
1103                 public static IEnumerable<TSource> Intersect<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
1104                 {
1105                         return Intersect (first, second, null);
1106                 }
1107
1108                 public static IEnumerable<TSource> Intersect<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
1109                 {
1110                         Check.FirstAndSecond (first, second);
1111
1112                         if (comparer == null)
1113                                 comparer = EqualityComparer<TSource>.Default;
1114
1115                         return CreateIntersectIterator (first, second, comparer);
1116                 }
1117
1118                 static IEnumerable<TSource> CreateIntersectIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
1119                 {
1120                         var items = new HashSet<TSource> (second, comparer);
1121                         foreach (TSource element in first) {
1122                                 if (items.Remove (element))
1123                                         yield return element;
1124                         }
1125                 }
1126
1127                 #endregion
1128
1129                 # region Join
1130
1131                 public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
1132                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
1133                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
1134                 {
1135                         Check.JoinSelectors (outer, inner, outerKeySelector, innerKeySelector, resultSelector);
1136
1137                         if (comparer == null)
1138                                 comparer = EqualityComparer<TKey>.Default;
1139
1140                         return CreateJoinIterator (outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
1141                 }
1142
1143                 static IEnumerable<TResult> CreateJoinIterator<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
1144                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
1145                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
1146                 {
1147                         ILookup<TKey, TInner> innerKeys = ToLookup<TInner, TKey> (inner, innerKeySelector, comparer);
1148                         /*Dictionary<K, List<U>> innerKeys = new Dictionary<K, List<U>> ();
1149                         foreach (U element in inner)
1150                         {
1151                                         K innerKey = innerKeySelector (element);
1152                                         if (!innerKeys.ContainsKey (innerKey))
1153                                                         innerKeys.Add (innerKey, new List<U> ());
1154                                         innerKeys[innerKey].Add (element);
1155                         }*/
1156
1157                         foreach (TOuter element in outer) {
1158                                 TKey outerKey = outerKeySelector (element);
1159                                 if (innerKeys.Contains (outerKey)) {
1160                                         foreach (TInner innerElement in innerKeys [outerKey])
1161                                                 yield return resultSelector (element, innerElement);
1162                                 }
1163                         }
1164                 }
1165
1166                 public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
1167                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
1168                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector)
1169                 {
1170                         return outer.Join (inner, outerKeySelector, innerKeySelector, resultSelector, null);
1171                 }
1172
1173                 #endregion
1174
1175                 #region Last
1176
1177                 static TSource Last<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate, Fallback fallback)
1178                 {
1179                         var empty = true;
1180                         var item = default (TSource);
1181
1182                         foreach (var element in source) {
1183                                 if (!predicate (element))
1184                                         continue;
1185
1186                                 item = element;
1187                                 empty = false;
1188                         }
1189
1190                         if (!empty)
1191                                 return item;
1192
1193                         if (fallback == Fallback.Throw)
1194                                 throw new InvalidOperationException ();
1195
1196                         return item;
1197                 }
1198
1199                 public static TSource Last<TSource> (this IEnumerable<TSource> source)
1200                 {
1201                         Check.Source (source);
1202
1203                         var collection = source as ICollection<TSource>;
1204                         if (collection != null && collection.Count == 0)
1205                                 throw new InvalidOperationException ();
1206
1207                         var list = source as IList<TSource>;
1208                         if (list != null)
1209                                 return list [list.Count - 1];
1210
1211                         return source.Last (PredicateOf<TSource>.Always, Fallback.Throw);
1212                 }
1213
1214                 public static TSource Last<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1215                 {
1216                         Check.SourceAndPredicate (source, predicate);
1217
1218                         return source.Last (predicate, Fallback.Throw);
1219                 }
1220
1221                 #endregion
1222
1223                 #region LastOrDefault
1224
1225                 public static TSource LastOrDefault<TSource> (this IEnumerable<TSource> source)
1226                 {
1227                         Check.Source (source);
1228
1229                         var list = source as IList<TSource>;
1230                         if (list != null)
1231                                 return list.Count > 0 ? list [list.Count - 1] : default (TSource);
1232
1233                         return source.Last (PredicateOf<TSource>.Always, Fallback.Default);
1234                 }
1235
1236                 public static TSource LastOrDefault<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1237                 {
1238                         Check.SourceAndPredicate (source, predicate);
1239
1240                         return source.Last (predicate, Fallback.Default);
1241                 }
1242
1243                 #endregion
1244
1245                 #region LongCount
1246
1247                 public static long LongCount<TSource> (this IEnumerable<TSource> source)
1248                 {
1249                         Check.Source (source);
1250
1251 #if !NET_2_1
1252                         var array = source as TSource [];
1253                         if (array != null)
1254                                 return array.LongLength;
1255 #endif
1256
1257                         long counter = 0;
1258                         using (var enumerator = source.GetEnumerator ())
1259                                 while (enumerator.MoveNext ())
1260                                         counter++;
1261
1262                         return counter;
1263                 }
1264
1265                 public static long LongCount<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1266                 {
1267                         Check.SourceAndSelector (source, predicate);
1268
1269                         long counter = 0;
1270                         foreach (TSource element in source)
1271                                 if (predicate (element))
1272                                         counter++;
1273
1274                         return counter;
1275                 }
1276
1277                 #endregion
1278
1279                 #region Max
1280
1281                 public static int Max (this IEnumerable<int> source)
1282                 {
1283                         Check.Source (source);
1284
1285                         bool empty = true;
1286                         var max = int.MinValue;
1287                         foreach (var element in source){
1288                                 max = Math.Max (element, max);
1289                                 empty = false;
1290                         }
1291                         if (empty)
1292                                 throw new InvalidOperationException ();
1293                         return max;
1294                 }
1295
1296                 public static long Max (this IEnumerable<long> source)
1297                 {
1298                         Check.Source (source);
1299
1300                         bool empty = true;
1301                         var max = long.MinValue;
1302                         foreach (var element in source){
1303                                 max = Math.Max (element, max);
1304                                 empty = false;
1305                         }
1306                         if (empty)
1307                                 throw new InvalidOperationException ();
1308                         return max;
1309                 }
1310
1311                 public static double Max (this IEnumerable<double> source)
1312                 {
1313                         Check.Source (source);
1314
1315                         bool empty = true;
1316                         var max = double.MinValue;
1317                         foreach (var element in source){
1318                                 max = Math.Max (element, max);
1319                                 empty = false;
1320                         }
1321                         if (empty)
1322                                 throw new InvalidOperationException ();
1323                         return max;
1324                 }
1325
1326                 public static float Max (this IEnumerable<float> source)
1327                 {
1328                         Check.Source (source);
1329
1330                         bool empty = true;
1331                         var max = float.MinValue;
1332                         foreach (var element in source){
1333                                 max = Math.Max (element, max);
1334                                 empty = false;
1335                         }
1336                         if (empty)
1337                                 throw new InvalidOperationException ();
1338                         return max;
1339                 }
1340
1341                 public static decimal Max (this IEnumerable<decimal> source)
1342                 {
1343                         Check.Source (source);
1344
1345                         bool empty = true;
1346                         var max = decimal.MinValue;
1347                         foreach (var element in source){
1348                                 max = Math.Max (element, max);
1349                                 empty = false;
1350                         }
1351                         if (empty)
1352                                 throw new InvalidOperationException ();
1353                         return max;
1354                 }
1355
1356                 public static int? Max (this IEnumerable<int?> source)
1357                 {
1358                         Check.Source (source);
1359
1360                         bool empty = true;
1361                         var max = int.MinValue;
1362                                 
1363                         foreach (var element in source) {
1364                                 if (!element.HasValue)
1365                                         continue;
1366
1367                                 max = Math.Max (element.Value, max);
1368                                 empty = false;
1369                         }
1370
1371                         if (empty)
1372                                 return null;
1373
1374                         return max;
1375                 }
1376
1377                 public static long? Max (this IEnumerable<long?> source)
1378                 {
1379                         Check.Source (source);
1380
1381                         bool empty = true;
1382                         var max = long.MinValue;
1383                                 
1384                         foreach (var element in source) {
1385                                 if (!element.HasValue)
1386                                         continue;
1387
1388                                 max = Math.Max (element.Value, max);
1389                                 empty = false;
1390                         }
1391
1392                         if (empty)
1393                                 return null;
1394
1395                         return max;
1396                 }
1397
1398                 public static double? Max (this IEnumerable<double?> source)
1399                 {
1400                         Check.Source (source);
1401
1402                         bool empty = true;
1403                         var max = double.MinValue;
1404                                 
1405                         foreach (var element in source) {
1406                                 if (!element.HasValue)
1407                                         continue;
1408
1409                                 max = Math.Max (element.Value, max);
1410                                 empty = false;
1411                         }
1412
1413                         if (empty)
1414                                 return null;
1415
1416                         return max;
1417                 }
1418
1419                 public static float? Max (this IEnumerable<float?> source)
1420                 {
1421                         Check.Source (source);
1422
1423                         bool empty = true;
1424                         var max = float.MinValue;
1425                                 
1426                         foreach (var element in source) {
1427                                 if (!element.HasValue)
1428                                         continue;
1429
1430                                 max = Math.Max (element.Value, max);
1431                                 empty = false;
1432                         }
1433
1434                         if (empty)
1435                                 return null;
1436
1437                         return max;
1438                 }
1439
1440                 public static decimal? Max (this IEnumerable<decimal?> source)
1441                 {
1442                         Check.Source (source);
1443
1444                         bool empty = true;
1445                         var max = decimal.MinValue;
1446                                 
1447                         foreach (var element in source) {
1448                                 if (!element.HasValue)
1449                                         continue;
1450
1451                                 max = Math.Max (element.Value, max);
1452                                 empty = false;
1453                         }
1454
1455                         if (empty)
1456                                 return null;
1457
1458                         return max;
1459                 }
1460
1461                 // TODO: test nullable and non-nullable
1462                 public static TSource Max<TSource> (this IEnumerable<TSource> source)
1463                 {
1464                         Check.Source (source);
1465
1466                         var comparer = Comparer<TSource>.Default;
1467
1468                         TSource max = default (TSource);
1469                         
1470                         if (default (TSource) == null){
1471                                 foreach (var element in source) {
1472                                         if (element == null)
1473                                                 continue;
1474
1475                                         if (max == null || comparer.Compare (element, max) > 0)
1476                                                 max = element;
1477                                 }
1478                         } else {
1479                                 bool empty = true;
1480                                 foreach (var element in source) {
1481                                         if (empty){
1482                                                 max = element;
1483                                                 empty = false;
1484                                                 continue;
1485                                         }
1486                                         if (comparer.Compare (element, max) > 0)
1487                                                 max = element;
1488                                 }
1489                                 if (empty)
1490                                         throw new InvalidOperationException ();
1491                         }
1492                         return max;
1493                 }
1494
1495                 public static int Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1496                 {
1497                         Check.SourceAndSelector (source, selector);
1498
1499                         bool empty = true;
1500                         var max = int.MinValue;
1501                         foreach (var element in source){
1502                                 max = Math.Max (selector (element), max);
1503                                 empty = false;
1504                         }
1505                         if (empty)
1506                                 throw new InvalidOperationException ();
1507                         return max;
1508                 }
1509
1510                 public static long Max<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1511                 {
1512                         Check.SourceAndSelector (source, selector);
1513
1514                         bool empty = true;
1515                         var max = long.MinValue;
1516                         foreach (var element in source){
1517                                 max = Math.Max (selector (element), max);
1518                                 empty = false;
1519                         }
1520                         if (empty)
1521                                 throw new InvalidOperationException ();
1522                         return max;
1523                 }
1524
1525                 public static double Max<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1526                 {
1527                         Check.SourceAndSelector (source, selector);
1528
1529                         bool empty = true;
1530                         var max = double.MinValue;
1531                         foreach (var element in source){
1532                                 max = Math.Max (selector (element), max);
1533                                 empty = false;
1534                         }
1535                         if (empty)
1536                                 throw new InvalidOperationException ();
1537                         return max;
1538                 }
1539
1540                 public static float Max<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1541                 {
1542                         Check.SourceAndSelector (source, selector);
1543
1544                         bool empty = true;
1545                         var max = float.MinValue;
1546                         foreach (var element in source){
1547                                 max = Math.Max (selector (element), max);
1548                                 empty = false;
1549                         }
1550                         if (empty)
1551                                 throw new InvalidOperationException ();
1552                         return max;
1553                 }
1554
1555                 public static decimal Max<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1556                 {
1557                         Check.SourceAndSelector (source, selector);
1558
1559                         bool empty = true;
1560                         var max = decimal.MinValue;
1561                         foreach (var element in source){
1562                                 max = Math.Max (selector (element), max);
1563                                 empty = false;
1564                         }
1565                         if (empty)
1566                                 throw new InvalidOperationException ();
1567                         return max;
1568                 }
1569
1570                 static U Iterate<T, U> (IEnumerable<T> source, U initValue, Func<T, U, U> selector)
1571                 {
1572                         bool empty = true;
1573                         foreach (var element in source) {
1574                                 initValue = selector (element, initValue);
1575                                 empty = false;
1576                         }
1577
1578                         if (empty)
1579                                 throw new InvalidOperationException ();
1580
1581                         return initValue;
1582                 }
1583
1584                 public static int? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1585                 {
1586                         Check.SourceAndSelector (source, selector);
1587
1588                         bool empty = true;
1589                         int? max = null;
1590                         foreach (var element in source) {
1591                                 int? item = selector (element);
1592
1593                                 if (!max.HasValue)
1594                                         max = item;
1595                                 else if (item > max)
1596                                         max = item;
1597                                 empty = false;
1598                         }
1599
1600                         if (empty)
1601                                 return null;
1602                         return max;
1603                 }
1604
1605                 public static long? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1606                 {
1607                         Check.SourceAndSelector (source, selector);
1608
1609                         bool empty = true;
1610                         long? max = null;
1611                         foreach (var element in source) {
1612                                 long? item = selector (element);
1613
1614                                 if (!max.HasValue)
1615                                         max = item;
1616                                 else if (item > max)
1617                                         max = item;
1618                                 empty = false;
1619                         }
1620
1621                         if (empty)
1622                                 return null;
1623                         return max;
1624                 }
1625
1626                 public static double? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1627                 {
1628                         Check.SourceAndSelector (source, selector);
1629
1630                         bool empty = true;
1631                         double? max = null;
1632                         foreach (var element in source) {
1633                                 double? item = selector (element);
1634
1635                                 if (!max.HasValue)
1636                                         max = item;
1637                                 else if (item > max)
1638                                         max = item;
1639                                 empty = false;
1640                         }
1641
1642                         if (empty)
1643                                 return null;
1644                         return max;
1645                 }
1646
1647                 public static float? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1648                 {
1649                         Check.SourceAndSelector (source, selector);
1650
1651                         bool empty = true;
1652                         float? max = null;
1653                         foreach (var element in source) {
1654                                 float? item = selector (element);
1655
1656                                 if (!max.HasValue)
1657                                         max = item;
1658                                 else if (item > max)
1659                                         max = item;
1660                                 empty = false;
1661                         }
1662
1663                         if (empty)
1664                                 return null;
1665                         return max;
1666                 }
1667
1668                 public static decimal? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1669                 {
1670                         Check.SourceAndSelector (source, selector);
1671
1672                         bool empty = true;
1673                         decimal? max = null;
1674                         foreach (var element in source) {
1675                                 decimal? item = selector (element);
1676
1677                                 if (!max.HasValue)
1678                                         max = item;
1679                                 else if (item > max)
1680                                         max = item;
1681                                 empty = false;
1682                         }
1683
1684                         if (empty)
1685                                 return null;
1686                         return max;
1687                 }
1688
1689                 public static TResult Max<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1690                 {
1691                         Check.SourceAndSelector (source, selector);
1692
1693                         // TODO: inline
1694                         return source.Select (selector).Max ();
1695                 }
1696
1697                 #endregion
1698
1699                 #region Min
1700
1701                 public static int Min (this IEnumerable<int> source)
1702                 {
1703                         Check.Source (source);
1704
1705                         bool empty = true;
1706                         var min = int.MaxValue;
1707                         foreach (var element in source){
1708                                 min = Math.Min (element, min);
1709                                 empty = false;
1710                         }
1711                         if (empty)
1712                                 throw new InvalidOperationException ();
1713                         return min;
1714                 }
1715
1716                 public static long Min (this IEnumerable<long> source)
1717                 {
1718                         Check.Source (source);
1719
1720                         bool empty = true;
1721                         var min = long.MaxValue;
1722                         foreach (var element in source){
1723                                 min = Math.Min (element, min);
1724                                 empty = false;
1725                         }
1726                         if (empty)
1727                                 throw new InvalidOperationException ();
1728                         return min;
1729                 }
1730
1731                 public static double Min (this IEnumerable<double> source)
1732                 {
1733                         Check.Source (source);
1734
1735                         bool empty = true;
1736                         var min = double.MaxValue;
1737                         foreach (var element in source){
1738                                 min = Math.Min (element, min);
1739                                 empty = false;
1740                         }
1741                         if (empty)
1742                                 throw new InvalidOperationException ();
1743                         return min;
1744                 }
1745
1746                 public static float Min (this IEnumerable<float> source)
1747                 {
1748                         Check.Source (source);
1749
1750                         bool empty = true;
1751                         var min = float.MaxValue;
1752                         foreach (var element in source){
1753                                 min = Math.Min (element, min);
1754                                 empty = false;
1755                         }
1756                         if (empty)
1757                                 throw new InvalidOperationException ();
1758                         return min;
1759                 }
1760
1761                 public static decimal Min (this IEnumerable<decimal> source)
1762                 {
1763                         Check.Source (source);
1764
1765                         bool empty = true;
1766                         var min = decimal.MaxValue;
1767                         foreach (var element in source){
1768                                 min = Math.Min (element, min);
1769                                 empty = false;
1770                         }
1771                         if (empty)
1772                                 throw new InvalidOperationException ();
1773                         return min;
1774                 }
1775
1776                 public static int? Min (this IEnumerable<int?> source)
1777                 {
1778                         Check.Source (source);
1779
1780                         bool empty = true;
1781                         var min = int.MaxValue;
1782                                 
1783                         foreach (var element in source) {
1784                                 if (!element.HasValue)
1785                                         continue;
1786
1787                                 min = Math.Min (element.Value, min);
1788                                 empty = false;
1789                         }
1790
1791                         if (empty)
1792                                 return null;
1793
1794                         return min;
1795                 }
1796
1797                 public static long? Min (this IEnumerable<long?> source)
1798                 {
1799                         Check.Source (source);
1800
1801                         bool empty = true;
1802                         var min = long.MaxValue;
1803                                 
1804                         foreach (var element in source) {
1805                                 if (!element.HasValue)
1806                                         continue;
1807
1808                                 min = Math.Min (element.Value, min);
1809                                 empty = false;
1810                         }
1811
1812                         if (empty)
1813                                 return null;
1814
1815                         return min;
1816                 }
1817
1818                 public static double? Min (this IEnumerable<double?> source)
1819                 {
1820                         Check.Source (source);
1821
1822                         bool empty = true;
1823                         var min = double.MaxValue;
1824                                 
1825                         foreach (var element in source) {
1826                                 if (!element.HasValue)
1827                                         continue;
1828
1829                                 min = Math.Min (element.Value, min);
1830                                 empty = false;
1831                         }
1832
1833                         if (empty)
1834                                 return null;
1835
1836                         return min;
1837                 }
1838
1839                 public static float? Min (this IEnumerable<float?> source)
1840                 {
1841                         Check.Source (source);
1842
1843                         bool empty = true;
1844                         var min = float.MaxValue;
1845                                 
1846                         foreach (var element in source) {
1847                                 if (!element.HasValue)
1848                                         continue;
1849
1850                                 min = Math.Min (element.Value, min);
1851                                 empty = false;
1852                         }
1853
1854                         if (empty)
1855                                 return null;
1856
1857                         return min;
1858                 }
1859
1860                 public static decimal? Min (this IEnumerable<decimal?> source)
1861                 {
1862                         Check.Source (source);
1863
1864                         bool empty = true;
1865                         var min = decimal.MaxValue;
1866                                 
1867                         foreach (var element in source) {
1868                                 if (!element.HasValue)
1869                                         continue;
1870
1871                                 min = Math.Min (element.Value, min);
1872                                 empty = false;
1873                         }
1874
1875                         if (empty)
1876                                 return null;
1877
1878                         return min;
1879                 }
1880
1881                 public static TSource Min<TSource> (this IEnumerable<TSource> source)
1882                 {
1883                         Check.Source (source);
1884
1885                         var comparer = Comparer<TSource>.Default;
1886
1887                         TSource min = default (TSource);
1888                         
1889                         if (default (TSource) == null){
1890                                 foreach (var element in source) {
1891                                         if (element == null)
1892                                                 continue;
1893
1894                                         if (min == null || comparer.Compare (element, min) < 0)
1895                                                 min = element;
1896                                 }
1897                         } else {
1898                                 bool empty = true;
1899                                 foreach (var element in source) {
1900                                         if (empty){
1901                                                 min = element;
1902                                                 empty = false;
1903                                                 continue;
1904                                         }
1905                                         if (comparer.Compare (element, min) < 0)
1906                                                 min = element;
1907                                 }
1908                                 if (empty)
1909                                         throw new InvalidOperationException ();
1910                         }
1911                         return min;
1912                 }
1913
1914                 public static int Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1915                 {
1916                         Check.SourceAndSelector (source, selector);
1917
1918                         bool empty = true;
1919                         var min = int.MaxValue;
1920                         foreach (var element in source){
1921                                 min = Math.Min (selector (element), min);
1922                                 empty = false;
1923                         }
1924                         if (empty)
1925                                 throw new InvalidOperationException ();
1926                         return min;
1927                 }
1928
1929                 public static long Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1930                 {
1931                         Check.SourceAndSelector (source, selector);
1932
1933                         bool empty = true;
1934                         var min = long.MaxValue;
1935                         foreach (var element in source){
1936                                 min = Math.Min (selector (element), min);
1937                                 empty = false;
1938                         }
1939                         if (empty)
1940                                 throw new InvalidOperationException ();
1941                         return min;
1942                 }
1943
1944                 public static double Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1945                 {
1946                         Check.SourceAndSelector (source, selector);
1947
1948                         bool empty = true;
1949                         var min = double.MaxValue;
1950                         foreach (var element in source){
1951                                 min = Math.Min (selector (element), min);
1952                                 empty = false;
1953                         }
1954                         if (empty)
1955                                 throw new InvalidOperationException ();
1956                         return min;
1957                 }
1958
1959                 public static float Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1960                 {
1961                         Check.SourceAndSelector (source, selector);
1962
1963                         bool empty = true;
1964                         var min = float.MaxValue;
1965                         foreach (var element in source){
1966                                 min = Math.Min (selector (element), min);
1967                                 empty = false;
1968                         }
1969                         if (empty)
1970                                 throw new InvalidOperationException ();
1971                         return min;
1972                 }
1973
1974                 public static decimal Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1975                 {
1976                         Check.SourceAndSelector (source, selector);
1977
1978                         bool empty = true;
1979                         var min = decimal.MaxValue;
1980                         foreach (var element in source){
1981                                 min = Math.Min (selector (element), min);
1982                                 empty = false;
1983                         }
1984                         if (empty)
1985                                 throw new InvalidOperationException ();
1986                         return min;
1987                 }
1988
1989                 public static int? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1990                 {
1991                         Check.SourceAndSelector (source, selector);
1992
1993                         bool empty = true;
1994                         int? min = null;
1995                         foreach (var element in source) {
1996                                 int? item = selector (element);
1997
1998                                 if (!min.HasValue)
1999                                         min = item;
2000                                 else if (item < min)
2001                                         min = item;
2002                                 empty = false;
2003                         }
2004
2005                         if (empty)
2006                                 return null;
2007                         return min;
2008                 }
2009
2010                 public static long? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
2011                 {
2012                         Check.SourceAndSelector (source, selector);
2013
2014                         bool empty = true;
2015                         long? min = null;
2016                         foreach (var element in source) {
2017                                 long? item = selector (element);
2018
2019                                 if (!min.HasValue)
2020                                         min = item;
2021                                 else if (item < min)
2022                                         min = item;
2023                                 empty = false;
2024                         }
2025
2026                         if (empty)
2027                                 return null;
2028                         return min;
2029                 }
2030
2031                 public static float? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
2032                 {
2033                         Check.SourceAndSelector (source, selector);
2034
2035                         bool empty = true;
2036                         float? min = null;
2037                         foreach (var element in source) {
2038                                 float? item = selector (element);
2039
2040                                 if (!min.HasValue)
2041                                         min = item;
2042                                 else if (item < min)
2043                                         min = item;
2044                                 empty = false;
2045                         }
2046
2047                         if (empty)
2048                                 return null;
2049                         return min;
2050                 }
2051
2052                 public static double? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
2053                 {
2054                         Check.SourceAndSelector (source, selector);
2055
2056                         bool empty = true;
2057                         double? min = null;
2058                         foreach (var element in source) {
2059                                 double? item = selector (element);
2060
2061                                 if (!min.HasValue)
2062                                         min = item;
2063                                 else if (item < min)
2064                                         min = item;
2065                                 empty = false;
2066                         }
2067
2068                         if (empty)
2069                                 return null;
2070                         return min;
2071                 }
2072
2073                 public static decimal? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
2074                 {
2075                         Check.SourceAndSelector (source, selector);
2076
2077                         bool empty = true;
2078                         decimal? min = null;
2079                         foreach (var element in source) {
2080                                 decimal? item = selector (element);
2081
2082                                 if (!min.HasValue)
2083                                         min = item;
2084                                 else if (item < min)
2085                                         min = item;
2086                                 empty = false;
2087                         }
2088
2089                         if (empty)
2090                                 return null;
2091                         return min;
2092                 }
2093
2094                 public static TResult Min<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
2095                 {
2096                         Check.SourceAndSelector (source, selector);
2097
2098                         // TODO: inline
2099                         return source.Select (selector).Min ();
2100                 }
2101
2102                 #endregion
2103
2104                 #region OfType
2105
2106                 public static IEnumerable<TResult> OfType<TResult> (this IEnumerable source)
2107                 {
2108                         Check.Source (source);
2109
2110                         return CreateOfTypeIterator<TResult> (source);
2111                 }
2112
2113                 static IEnumerable<TResult> CreateOfTypeIterator<TResult> (IEnumerable source)
2114                 {
2115                         foreach (object element in source)
2116                                 if (element is TResult)
2117                                         yield return (TResult) element;
2118                 }
2119
2120                 #endregion
2121
2122                 #region OrderBy
2123
2124                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
2125                                 Func<TSource, TKey> keySelector)
2126                 {
2127                         return OrderBy<TSource, TKey> (source, keySelector, null);
2128                 }
2129
2130                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
2131                                 Func<TSource, TKey> keySelector,
2132                                 IComparer<TKey> comparer)
2133                 {
2134                         Check.SourceAndKeySelector (source, keySelector);
2135
2136                         return new OrderedSequence<TSource, TKey> (source, keySelector, comparer, SortDirection.Ascending);
2137                 }
2138
2139                 #endregion
2140
2141                 #region OrderByDescending
2142
2143                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
2144                                 Func<TSource, TKey> keySelector)
2145                 {
2146                         return OrderByDescending<TSource, TKey> (source, keySelector, null);
2147                 }
2148
2149                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
2150                                 Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2151                 {
2152                         Check.SourceAndKeySelector (source, keySelector);
2153
2154                         return new OrderedSequence<TSource, TKey> (source, keySelector, comparer, SortDirection.Descending);
2155                 }
2156
2157                 #endregion
2158
2159                 #region Range
2160
2161                 public static IEnumerable<int> Range (int start, int count)
2162                 {
2163                         if (count < 0)
2164                                 throw new ArgumentOutOfRangeException ("count");
2165
2166                         if (((long) start + count) - 1L > int.MaxValue)
2167                                 throw new ArgumentOutOfRangeException ();
2168
2169                         return CreateRangeIterator (start, count);
2170                 }
2171
2172                 static IEnumerable<int> CreateRangeIterator (int start, int count)
2173                 {
2174                         for (int i = 0; i < count; i++)
2175                                 yield return start + i;
2176                 }
2177
2178                 #endregion
2179
2180                 #region Repeat
2181
2182                 public static IEnumerable<TResult> Repeat<TResult> (TResult element, int count)
2183                 {
2184                         if (count < 0)
2185                                 throw new ArgumentOutOfRangeException ();
2186
2187                         return CreateRepeatIterator (element, count);
2188                 }
2189
2190                 static IEnumerable<TResult> CreateRepeatIterator<TResult> (TResult element, int count)
2191                 {
2192                         for (int i = 0; i < count; i++)
2193                                 yield return element;
2194                 }
2195
2196                 #endregion
2197
2198                 #region Reverse
2199
2200                 public static IEnumerable<TSource> Reverse<TSource> (this IEnumerable<TSource> source)
2201                 {
2202                         Check.Source (source);
2203
2204                         return CreateReverseIterator (source);
2205                 }
2206
2207                 static IEnumerable<TSource> CreateReverseIterator<TSource> (IEnumerable<TSource> source)
2208                 {
2209                         var list = source as IList<TSource>;
2210                         if (list == null)
2211                                 list = new List<TSource> (source);
2212
2213                         for (int i = list.Count - 1; i >= 0; i--)
2214                                 yield return list [i];
2215                 }
2216
2217                 #endregion
2218
2219                 #region Select
2220
2221                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
2222                 {
2223                         Check.SourceAndSelector (source, selector);
2224
2225                         return CreateSelectIterator (source, selector);
2226                 }
2227
2228                 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, TResult> selector)
2229                 {
2230                         foreach (var element in source)
2231                                 yield return selector (element);
2232                 }
2233
2234                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
2235                 {
2236                         Check.SourceAndSelector (source, selector);
2237
2238                         return CreateSelectIterator (source, selector);
2239                 }
2240
2241                 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
2242                 {
2243                         int counter = 0;
2244                         foreach (TSource element in source) {
2245                                 yield return selector (element, counter);
2246                                 counter++;
2247                         }
2248                 }
2249
2250                 #endregion
2251
2252                 #region SelectMany
2253
2254                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
2255                 {
2256                         Check.SourceAndSelector (source, selector);
2257
2258                         return CreateSelectManyIterator (source, selector);
2259                 }
2260
2261                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
2262                 {
2263                         foreach (TSource element in source)
2264                                 foreach (TResult item in selector (element))
2265                                         yield return item;
2266                 }
2267
2268                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
2269                 {
2270                         Check.SourceAndSelector (source, selector);
2271
2272                         return CreateSelectManyIterator (source, selector);
2273                 }
2274
2275                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
2276                 {
2277                         int counter = 0;
2278                         foreach (TSource element in source) {
2279                                 foreach (TResult item in selector (element, counter))
2280                                         yield return item;
2281                                 counter++;
2282                         }
2283                 }
2284
2285                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
2286                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
2287                 {
2288                         Check.SourceAndCollectionSelectors (source, collectionSelector, resultSelector);
2289
2290                         return CreateSelectManyIterator (source, collectionSelector, resultSelector);
2291                 }
2292
2293                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult> (IEnumerable<TSource> source,
2294                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
2295                 {
2296                         foreach (TSource element in source)
2297                                 foreach (TCollection collection in collectionSelector (element))
2298                                         yield return selector (element, collection);
2299                 }
2300
2301                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
2302                         Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
2303                 {
2304                         Check.SourceAndCollectionSelectors (source, collectionSelector, resultSelector);
2305
2306                         return CreateSelectManyIterator (source, collectionSelector, resultSelector);
2307                 }
2308
2309                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult> (IEnumerable<TSource> source,
2310                         Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
2311                 {
2312                         int counter = 0;
2313                         foreach (TSource element in source)
2314                                 foreach (TCollection collection in collectionSelector (element, counter++))
2315                                         yield return selector (element, collection);
2316                 }
2317
2318                 #endregion
2319
2320                 #region Single
2321
2322                 static TSource Single<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate, Fallback fallback)
2323                 {
2324                         var found = false;
2325                         var item = default (TSource);
2326
2327                         foreach (var element in source) {
2328                                 if (!predicate (element))
2329                                         continue;
2330
2331                                 if (found)
2332                                         throw new InvalidOperationException ();
2333
2334                                 found = true;
2335                                 item = element;
2336                         }
2337
2338                         if (!found && fallback == Fallback.Throw)
2339                                 throw new InvalidOperationException ();
2340
2341                         return item;
2342                 }
2343
2344                 public static TSource Single<TSource> (this IEnumerable<TSource> source)
2345                 {
2346                         Check.Source (source);
2347
2348                         return source.Single (PredicateOf<TSource>.Always, Fallback.Throw);
2349                 }
2350
2351                 public static TSource Single<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2352                 {
2353                         Check.SourceAndPredicate (source, predicate);
2354
2355                         return source.Single (predicate, Fallback.Throw);
2356                 }
2357
2358                 #endregion
2359
2360                 #region SingleOrDefault
2361
2362                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source)
2363                 {
2364                         Check.Source (source);
2365
2366                         return source.Single (PredicateOf<TSource>.Always, Fallback.Default);
2367                 }
2368
2369                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2370                 {
2371                         Check.SourceAndPredicate (source, predicate);
2372
2373                         return source.Single (predicate, Fallback.Default);
2374                 }
2375
2376                 #endregion
2377
2378                 #region Skip
2379
2380                 public static IEnumerable<TSource> Skip<TSource> (this IEnumerable<TSource> source, int count)
2381                 {
2382                         Check.Source (source);
2383
2384                         return CreateSkipIterator (source, count);
2385                 }
2386
2387                 static IEnumerable<TSource> CreateSkipIterator<TSource> (IEnumerable<TSource> source, int count)
2388                 {
2389                         var enumerator = source.GetEnumerator ();
2390                         try {
2391                                 while (count-- > 0)
2392                                         if (!enumerator.MoveNext ())
2393                                                 yield break;
2394
2395                                 while (enumerator.MoveNext ())
2396                                         yield return enumerator.Current;
2397
2398                         } finally {
2399                                 enumerator.Dispose ();
2400                         }
2401                 }
2402
2403                 #endregion
2404
2405                 #region SkipWhile
2406
2407                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2408                 {
2409                         Check.SourceAndPredicate (source, predicate);
2410
2411                         return CreateSkipWhileIterator (source, predicate);
2412                 }
2413
2414                 static IEnumerable<TSource> CreateSkipWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
2415                 {
2416                         bool yield = false;
2417
2418                         foreach (TSource element in source) {
2419                                 if (yield)
2420                                         yield return element;
2421                                 else
2422                                         if (!predicate (element)) {
2423                                                 yield return element;
2424                                                 yield = true;
2425                                         }
2426                         }
2427                 }
2428
2429                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2430                 {
2431                         Check.SourceAndPredicate (source, predicate);
2432
2433                         return CreateSkipWhileIterator (source, predicate);
2434                 }
2435
2436                 static IEnumerable<TSource> CreateSkipWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2437                 {
2438                         int counter = 0;
2439                         bool yield = false;
2440
2441                         foreach (TSource element in source) {
2442                                 if (yield)
2443                                         yield return element;
2444                                 else
2445                                         if (!predicate (element, counter)) {
2446                                                 yield return element;
2447                                                 yield = true;
2448                                         }
2449                                 counter++;
2450                         }
2451                 }
2452
2453                 #endregion
2454
2455                 #region Sum
2456
2457                 public static int Sum (this IEnumerable<int> source)
2458                 {
2459                         Check.Source (source);
2460                         int total = 0;
2461                         
2462                         foreach (var element in source)
2463                                 total = checked (total + element);
2464                         return total;
2465                 }
2466
2467                 public static int? Sum (this IEnumerable<int?> source)
2468                 {
2469                         Check.Source (source);
2470
2471                         int total = 0;
2472                         foreach (var element in source) {
2473                                 if (element.HasValue)
2474                                         total = checked (total + element.Value);
2475                         }
2476                         return total;
2477                 }
2478
2479                 public static int Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
2480                 {
2481                         Check.SourceAndSelector (source, selector);
2482                         int total = 0;
2483
2484                         foreach (var element in source)
2485                                 total = checked (total + selector (element));
2486
2487                         return total;
2488                 }
2489
2490                 public static int? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
2491                 {
2492                         Check.SourceAndSelector (source, selector);
2493
2494                         int total = 0;
2495                         foreach (var element in source) {
2496                                 var value = selector (element);
2497                                 if (value.HasValue)
2498                                         total = checked (total + value.Value);
2499                         }
2500                         return total;
2501                 }
2502
2503                 public static long Sum (this IEnumerable<long> source)
2504                 {
2505                         Check.Source (source);
2506
2507                         long total = 0;
2508                         
2509                         foreach (var element in source)
2510                                 total = checked (total + element);
2511                         return total;
2512                 }
2513
2514                 public static long? Sum (this IEnumerable<long?> source)
2515                 {
2516                         Check.Source (source);
2517
2518                         long total = 0;
2519                         foreach (var element in source) {
2520                                 if (element.HasValue)
2521                                         total = checked (total + element.Value);
2522                         }
2523                         return total;
2524                 }
2525
2526                 public static long Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
2527                 {
2528                         Check.SourceAndSelector (source, selector);
2529
2530                         long total = 0;
2531                         foreach (var element in source)
2532                                 total = checked (total + selector (element));
2533                         return total;
2534                 }
2535
2536                 public static long? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
2537                 {
2538                         Check.SourceAndSelector (source, selector);
2539
2540                         long total = 0;
2541                         foreach (var element in source) {
2542                                 var value = selector (element);
2543                                 if (value.HasValue)
2544                                         total = checked (total + value.Value);
2545                         }
2546                         return total;
2547                 }
2548
2549                 public static double Sum (this IEnumerable<double> source)
2550                 {
2551                         Check.Source (source);
2552
2553                         double total = 0;
2554                         
2555                         foreach (var element in source)
2556                                 total = checked (total + element);
2557                         return total;
2558                 }
2559
2560                 public static double? Sum (this IEnumerable<double?> source)
2561                 {
2562                         Check.Source (source);
2563
2564                         double total = 0;
2565                         foreach (var element in source) {
2566                                 if (element.HasValue)
2567                                         total = checked (total + element.Value);
2568                         }
2569                         return total;
2570                 }
2571
2572                 public static double Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
2573                 {
2574                         Check.SourceAndSelector (source, selector);
2575
2576                         double total = 0;
2577                         
2578                         foreach (var element in source)
2579                                 total = checked (total + selector (element));
2580                         return total;
2581                 }
2582
2583                 public static double? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
2584                 {
2585                         Check.SourceAndSelector (source, selector);
2586
2587                         double total = 0;
2588                         foreach (var element in source) {
2589                                 var value = selector (element);
2590                                 if (value.HasValue)
2591                                         total = checked (total + value.Value);
2592                         }
2593                         return total;
2594                 }
2595
2596                 public static float Sum (this IEnumerable<float> source)
2597                 {
2598                         Check.Source (source);
2599
2600                         float total = 0;
2601                         
2602                         foreach (var element in source)
2603                                 total = checked (total + element);
2604                         return total;
2605                 }
2606
2607                 public static float? Sum (this IEnumerable<float?> source)
2608                 {
2609                         Check.Source (source);
2610
2611                         float total = 0;
2612                         foreach (var element in source) {
2613                                 if (element.HasValue)
2614                                         total = checked (total + element.Value);
2615                         }
2616                         return total;
2617
2618                 }
2619
2620                 public static float Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
2621                 {
2622                         Check.SourceAndSelector (source, selector);
2623                         float total = 0;
2624                         foreach (var element in source)
2625                                 total = checked (total + selector (element));
2626                         return total;
2627                 }
2628
2629                 public static float? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
2630                 {
2631                         Check.SourceAndSelector (source, selector);
2632
2633                         float total = 0;
2634                         foreach (var element in source) {
2635                                 var value = selector (element);
2636                                 if (value.HasValue)
2637                                         total = checked (total + value.Value);
2638                         }
2639                         return total;
2640                 }
2641
2642                 public static decimal Sum (this IEnumerable<decimal> source)
2643                 {
2644                         Check.Source (source);
2645                         decimal total = 0;
2646                         
2647                         foreach (var element in source)
2648                                 total = checked (total + element);
2649                         return total;
2650                 }
2651
2652                 public static decimal? Sum (this IEnumerable<decimal?> source)
2653                 {
2654                         Check.Source (source);
2655
2656                         decimal total = 0;
2657                         foreach (var element in source) {
2658                                 if (element.HasValue)
2659                                         total = checked (total + element.Value);
2660                         }
2661                         return total;
2662
2663                 }
2664
2665                 public static decimal Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
2666                 {
2667                         Check.SourceAndSelector (source, selector);
2668                         decimal total = 0;
2669                         
2670                         foreach (var element in source)
2671                                 total = checked (total + selector (element));
2672                         return total;
2673                 }
2674
2675                 public static decimal? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
2676                 {
2677                         Check.SourceAndSelector (source, selector);
2678
2679                         decimal total = 0;
2680                         foreach (var element in source) {
2681                                 var value = selector (element);
2682                                 if (value.HasValue)
2683                                         total = checked (total + value.Value);
2684                         }
2685                         return total;
2686                 }
2687
2688                 #endregion
2689
2690                 #region Take
2691
2692                 public static IEnumerable<TSource> Take<TSource> (this IEnumerable<TSource> source, int count)
2693                 {
2694                         Check.Source (source);
2695
2696                         return CreateTakeIterator (source, count);
2697                 }
2698
2699                 static IEnumerable<TSource> CreateTakeIterator<TSource> (IEnumerable<TSource> source, int count)
2700                 {
2701                         if (count <= 0)
2702                                 yield break;
2703
2704                         int counter = 0;
2705                         foreach (TSource element in source) {
2706                                 yield return element;
2707
2708                                 if (++counter == count)
2709                                         yield break;
2710                         }
2711                 }
2712
2713                 #endregion
2714
2715                 #region TakeWhile
2716
2717                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2718                 {
2719                         Check.SourceAndPredicate (source, predicate);
2720
2721                         return CreateTakeWhileIterator (source, predicate);
2722                 }
2723
2724                 static IEnumerable<TSource> CreateTakeWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
2725                 {
2726                         foreach (var element in source) {
2727                                 if (!predicate (element))
2728                                         yield break;
2729
2730                                 yield return element;
2731                         }
2732                 }
2733
2734                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2735                 {
2736                         Check.SourceAndPredicate (source, predicate);
2737
2738                         return CreateTakeWhileIterator (source, predicate);
2739                 }
2740
2741                 static IEnumerable<TSource> CreateTakeWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2742                 {
2743                         int counter = 0;
2744                         foreach (var element in source) {
2745                                 if (!predicate (element, counter))
2746                                         yield break;
2747
2748                                 yield return element;
2749                                 counter++;
2750                         }
2751                 }
2752
2753                 #endregion
2754
2755                 #region ThenBy
2756
2757                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2758                 {
2759                         return ThenBy<TSource, TKey> (source, keySelector, null);
2760                 }
2761
2762                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2763                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2764                 {
2765                         Check.SourceAndKeySelector (source, keySelector);
2766
2767                         return source.CreateOrderedEnumerable (keySelector, comparer, false);
2768                 }
2769
2770                 #endregion
2771
2772                 #region ThenByDescending
2773
2774                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2775                         Func<TSource, TKey> keySelector)
2776                 {
2777                         return ThenByDescending<TSource, TKey> (source, keySelector, null);
2778                 }
2779
2780                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2781                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2782                 {
2783                         Check.SourceAndKeySelector (source, keySelector);
2784
2785                         return source.CreateOrderedEnumerable (keySelector, comparer, true);
2786                 }
2787
2788                 #endregion
2789
2790                 #region ToArray
2791
2792                 public static TSource [] ToArray<TSource> (this IEnumerable<TSource> source)
2793                 {
2794                         Check.Source (source);
2795
2796                         var collection = source as ICollection<TSource>;
2797                         if (collection != null) {
2798                                 var array = new TSource [collection.Count];
2799                                 collection.CopyTo (array, 0);
2800                                 return array;
2801                         }
2802
2803                         return new List<TSource> (source).ToArray ();
2804                 }
2805
2806                 #endregion
2807
2808                 #region ToDictionary
2809                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2810                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2811                 {
2812                         return ToDictionary<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2813                 }
2814
2815                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2816                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2817                 {
2818                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2819
2820                         if (comparer == null)
2821                                 comparer = EqualityComparer<TKey>.Default;
2822
2823                         var dict = new Dictionary<TKey, TElement> (comparer);
2824                         foreach (var e in source)
2825                                 dict.Add (keySelector (e), elementSelector (e));
2826
2827                         return dict;
2828                 }
2829
2830                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2831                                 Func<TSource, TKey> keySelector)
2832                 {
2833                         return ToDictionary (source, keySelector, null);
2834                 }
2835
2836                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2837                                 Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2838                 {
2839                         return ToDictionary<TSource, TKey, TSource> (source, keySelector, Function<TSource>.Identity, comparer);
2840                 }
2841
2842                 #endregion
2843
2844                 #region ToList
2845                 public static List<TSource> ToList<TSource> (this IEnumerable<TSource> source)
2846                 {
2847                         Check.Source (source);
2848
2849                         return new List<TSource> (source);
2850                 }
2851                 #endregion
2852
2853                 #region ToLookup
2854
2855                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2856                 {
2857                         return ToLookup<TSource, TKey, TSource> (source, keySelector, Function<TSource>.Identity, null);
2858                 }
2859
2860                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source,
2861                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2862                 {
2863                         return ToLookup<TSource, TKey, TSource> (source, keySelector, element => element, comparer);
2864                 }
2865
2866                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2867                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2868                 {
2869                         return ToLookup<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2870                 }
2871
2872                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2873                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2874                 {
2875                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2876
2877                         List<TElement> nullKeyElements = null;
2878                         
2879                         var dictionary = new Dictionary<TKey, List<TElement>> (comparer ?? EqualityComparer<TKey>.Default);
2880                         foreach (var element in source) {
2881                                 var key = keySelector (element);
2882
2883                                 List<TElement> list;
2884                                 
2885                                 if (key == null) {
2886                                         if (nullKeyElements == null)
2887                                                 nullKeyElements = new List<TElement> ();
2888                                         
2889                                         list = nullKeyElements;
2890                                 } else if (!dictionary.TryGetValue (key, out list)) {
2891                                         list = new List<TElement> ();
2892                                         dictionary.Add (key, list);
2893                                 }
2894
2895                                 list.Add (elementSelector (element));
2896                         }
2897
2898                         return new Lookup<TKey, TElement> (dictionary, nullKeyElements);
2899                 }
2900
2901                 #endregion
2902
2903                 #region SequenceEqual
2904
2905                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2906                 {
2907                         return first.SequenceEqual (second, null);
2908                 }
2909
2910                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2911                 {
2912                         Check.FirstAndSecond (first, second);
2913
2914                         if (comparer == null)
2915                                 comparer = EqualityComparer<TSource>.Default;
2916
2917                         using (IEnumerator<TSource> first_enumerator = first.GetEnumerator (),
2918                                 second_enumerator = second.GetEnumerator ()) {
2919
2920                                 while (first_enumerator.MoveNext ()) {
2921                                         if (!second_enumerator.MoveNext ())
2922                                                 return false;
2923
2924                                         if (!comparer.Equals (first_enumerator.Current, second_enumerator.Current))
2925                                                 return false;
2926                                 }
2927
2928                                 return !second_enumerator.MoveNext ();
2929                         }
2930                 }
2931
2932                 #endregion
2933
2934                 #region Union
2935
2936                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2937                 {
2938                         Check.FirstAndSecond (first, second);
2939
2940                         return first.Union (second, null);
2941                 }
2942
2943                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2944                 {
2945                         Check.FirstAndSecond (first, second);
2946
2947                         if (comparer == null)
2948                                 comparer = EqualityComparer<TSource>.Default;
2949
2950                         return CreateUnionIterator (first, second, comparer);
2951                 }
2952
2953                 static IEnumerable<TSource> CreateUnionIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2954                 {
2955                         var items = new HashSet<TSource> (comparer);
2956                         foreach (var element in first) {
2957                                 if (! items.Contains (element)) {
2958                                         items.Add (element);
2959                                         yield return element;
2960                                 }
2961                         }
2962
2963                         foreach (var element in second) {
2964                                 if (! items.Contains (element)) {
2965                                         items.Add (element);
2966                                         yield return element;
2967                                 }
2968                         }
2969                 }
2970
2971                 #endregion
2972                 
2973 #if NET_4_0 || MOONLIGHT
2974                 #region Zip
2975                 
2976                 public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult> (this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
2977                 {
2978                         Check.FirstAndSecond (first, second);
2979                         if (resultSelector == null)
2980                                 throw new ArgumentNullException ("resultSelector");
2981                                 
2982                         return CreateZipIterator (first, second, resultSelector);
2983                 }
2984                 
2985                 static IEnumerable<TResult> CreateZipIterator<TFirst, TSecond, TResult> (IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> selector)
2986                 {
2987                         using (IEnumerator<TFirst> first_enumerator = first.GetEnumerator ()) {
2988                                 using (IEnumerator<TSecond> second_enumerator = second.GetEnumerator ()) {
2989
2990                                         while (first_enumerator.MoveNext () && second_enumerator.MoveNext ()) {
2991                                                 yield return selector (first_enumerator.Current, second_enumerator.Current);
2992                                         }
2993                                 }
2994                         }
2995                 }
2996                 
2997                 #endregion
2998 #endif          
2999
3000                 #region Where
3001
3002                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
3003                 {
3004                         Check.SourceAndPredicate (source, predicate);
3005
3006                         return CreateWhereIterator (source, predicate);
3007                 }
3008
3009                 static IEnumerable<TSource> CreateWhereIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
3010                 {
3011                         foreach (TSource element in source)
3012                                 if (predicate (element))
3013                                         yield return element;
3014                 }
3015
3016                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
3017                 {
3018                         Check.SourceAndPredicate (source, predicate);
3019
3020                         return CreateWhereIterator (source, predicate);
3021                 }
3022
3023                 static IEnumerable<TSource> CreateWhereIterator<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
3024                 {
3025                         int counter = 0;
3026                         foreach (TSource element in source) {
3027                                 if (predicate (element, counter))
3028                                         yield return element;
3029                                 counter++;
3030                         }
3031                 }
3032
3033                 #endregion
3034
3035                 internal static ReadOnlyCollection<TSource> ToReadOnlyCollection<TSource> (this IEnumerable<TSource> source)
3036                 {
3037                         if (source == null)
3038                                 return ReadOnlyCollectionOf<TSource>.Empty;
3039
3040                         var ro = source as ReadOnlyCollection<TSource>;
3041                         if (ro != null)
3042                                 return ro;
3043
3044                         return new ReadOnlyCollection<TSource> (source.ToArray<TSource> ());
3045                 }
3046         }
3047 }