Merge branch 'master' of github.com:mono/mono
[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> selector)
646                 {
647                         Check.SourceAndSelector (source, selector);
648
649                         int counter = 0;
650                         foreach (var element in source)
651                                 if (selector (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> selector)
1266                 {
1267                         Check.SourceAndSelector (source, selector);
1268
1269                         long counter = 0;
1270                         foreach (TSource element in source)
1271                                 if (selector (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                         long upto = ((long) start + count) - 1;
2167
2168                         if (upto > int.MaxValue)
2169                                 throw new ArgumentOutOfRangeException ();
2170
2171                         return CreateRangeIterator (start, (int) upto);
2172                 }
2173
2174                 static IEnumerable<int> CreateRangeIterator (int start, int upto)
2175                 {
2176                         for (int i = start; i <= upto; i++)
2177                                 yield return i;
2178                 }
2179
2180                 #endregion
2181
2182                 #region Repeat
2183
2184                 public static IEnumerable<TResult> Repeat<TResult> (TResult element, int count)
2185                 {
2186                         if (count < 0)
2187                                 throw new ArgumentOutOfRangeException ();
2188
2189                         return CreateRepeatIterator (element, count);
2190                 }
2191
2192                 static IEnumerable<TResult> CreateRepeatIterator<TResult> (TResult element, int count)
2193                 {
2194                         for (int i = 0; i < count; i++)
2195                                 yield return element;
2196                 }
2197
2198                 #endregion
2199
2200                 #region Reverse
2201
2202                 public static IEnumerable<TSource> Reverse<TSource> (this IEnumerable<TSource> source)
2203                 {
2204                         Check.Source (source);
2205
2206                         return CreateReverseIterator (source);
2207                 }
2208
2209                 static IEnumerable<TSource> CreateReverseIterator<TSource> (IEnumerable<TSource> source)
2210                 {
2211                         var list = source as IList<TSource>;
2212                         if (list == null)
2213                                 list = new List<TSource> (source);
2214
2215                         for (int i = list.Count - 1; i >= 0; i--)
2216                                 yield return list [i];
2217                 }
2218
2219                 #endregion
2220
2221                 #region Select
2222
2223                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
2224                 {
2225                         Check.SourceAndSelector (source, selector);
2226
2227                         return CreateSelectIterator (source, selector);
2228                 }
2229
2230                 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, TResult> selector)
2231                 {
2232                         foreach (var element in source)
2233                                 yield return selector (element);
2234                 }
2235
2236                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
2237                 {
2238                         Check.SourceAndSelector (source, selector);
2239
2240                         return CreateSelectIterator (source, selector);
2241                 }
2242
2243                 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
2244                 {
2245                         int counter = 0;
2246                         foreach (TSource element in source) {
2247                                 yield return selector (element, counter);
2248                                 counter++;
2249                         }
2250                 }
2251
2252                 #endregion
2253
2254                 #region SelectMany
2255
2256                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
2257                 {
2258                         Check.SourceAndSelector (source, selector);
2259
2260                         return CreateSelectManyIterator (source, selector);
2261                 }
2262
2263                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
2264                 {
2265                         foreach (TSource element in source)
2266                                 foreach (TResult item in selector (element))
2267                                         yield return item;
2268                 }
2269
2270                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
2271                 {
2272                         Check.SourceAndSelector (source, selector);
2273
2274                         return CreateSelectManyIterator (source, selector);
2275                 }
2276
2277                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
2278                 {
2279                         int counter = 0;
2280                         foreach (TSource element in source) {
2281                                 foreach (TResult item in selector (element, counter))
2282                                         yield return item;
2283                                 counter++;
2284                         }
2285                 }
2286
2287                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
2288                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
2289                 {
2290                         Check.SourceAndCollectionSelectors (source, collectionSelector, selector);
2291
2292                         return CreateSelectManyIterator (source, collectionSelector, selector);
2293                 }
2294
2295                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult> (IEnumerable<TSource> source,
2296                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
2297                 {
2298                         foreach (TSource element in source)
2299                                 foreach (TCollection collection in collectionSelector (element))
2300                                         yield return selector (element, collection);
2301                 }
2302
2303                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
2304                         Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
2305                 {
2306                         Check.SourceAndCollectionSelectors (source, collectionSelector, selector);
2307
2308                         return CreateSelectManyIterator (source, collectionSelector, selector);
2309                 }
2310
2311                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult> (IEnumerable<TSource> source,
2312                         Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
2313                 {
2314                         int counter = 0;
2315                         foreach (TSource element in source)
2316                                 foreach (TCollection collection in collectionSelector (element, counter++))
2317                                         yield return selector (element, collection);
2318                 }
2319
2320                 #endregion
2321
2322                 #region Single
2323
2324                 static TSource Single<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate, Fallback fallback)
2325                 {
2326                         var found = false;
2327                         var item = default (TSource);
2328
2329                         foreach (var element in source) {
2330                                 if (!predicate (element))
2331                                         continue;
2332
2333                                 if (found)
2334                                         throw new InvalidOperationException ();
2335
2336                                 found = true;
2337                                 item = element;
2338                         }
2339
2340                         if (!found && fallback == Fallback.Throw)
2341                                 throw new InvalidOperationException ();
2342
2343                         return item;
2344                 }
2345
2346                 public static TSource Single<TSource> (this IEnumerable<TSource> source)
2347                 {
2348                         Check.Source (source);
2349
2350                         return source.Single (PredicateOf<TSource>.Always, Fallback.Throw);
2351                 }
2352
2353                 public static TSource Single<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2354                 {
2355                         Check.SourceAndPredicate (source, predicate);
2356
2357                         return source.Single (predicate, Fallback.Throw);
2358                 }
2359
2360                 #endregion
2361
2362                 #region SingleOrDefault
2363
2364                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source)
2365                 {
2366                         Check.Source (source);
2367
2368                         return source.Single (PredicateOf<TSource>.Always, Fallback.Default);
2369                 }
2370
2371                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2372                 {
2373                         Check.SourceAndPredicate (source, predicate);
2374
2375                         return source.Single (predicate, Fallback.Default);
2376                 }
2377
2378                 #endregion
2379
2380                 #region Skip
2381
2382                 public static IEnumerable<TSource> Skip<TSource> (this IEnumerable<TSource> source, int count)
2383                 {
2384                         Check.Source (source);
2385
2386                         return CreateSkipIterator (source, count);
2387                 }
2388
2389                 static IEnumerable<TSource> CreateSkipIterator<TSource> (IEnumerable<TSource> source, int count)
2390                 {
2391                         var enumerator = source.GetEnumerator ();
2392                         try {
2393                                 while (count-- > 0)
2394                                         if (!enumerator.MoveNext ())
2395                                                 yield break;
2396
2397                                 while (enumerator.MoveNext ())
2398                                         yield return enumerator.Current;
2399
2400                         } finally {
2401                                 enumerator.Dispose ();
2402                         }
2403                 }
2404
2405                 #endregion
2406
2407                 #region SkipWhile
2408
2409                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2410                 {
2411                         Check.SourceAndPredicate (source, predicate);
2412
2413                         return CreateSkipWhileIterator (source, predicate);
2414                 }
2415
2416                 static IEnumerable<TSource> CreateSkipWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
2417                 {
2418                         bool yield = false;
2419
2420                         foreach (TSource element in source) {
2421                                 if (yield)
2422                                         yield return element;
2423                                 else
2424                                         if (!predicate (element)) {
2425                                                 yield return element;
2426                                                 yield = true;
2427                                         }
2428                         }
2429                 }
2430
2431                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2432                 {
2433                         Check.SourceAndPredicate (source, predicate);
2434
2435                         return CreateSkipWhileIterator (source, predicate);
2436                 }
2437
2438                 static IEnumerable<TSource> CreateSkipWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2439                 {
2440                         int counter = 0;
2441                         bool yield = false;
2442
2443                         foreach (TSource element in source) {
2444                                 if (yield)
2445                                         yield return element;
2446                                 else
2447                                         if (!predicate (element, counter)) {
2448                                                 yield return element;
2449                                                 yield = true;
2450                                         }
2451                                 counter++;
2452                         }
2453                 }
2454
2455                 #endregion
2456
2457                 #region Sum
2458
2459                 public static int Sum (this IEnumerable<int> source)
2460                 {
2461                         Check.Source (source);
2462                         int total = 0;
2463                         
2464                         foreach (var element in source)
2465                                 total = checked (total + element);
2466                         return total;
2467                 }
2468
2469                 public static int? Sum (this IEnumerable<int?> source)
2470                 {
2471                         Check.Source (source);
2472
2473                         int total = 0;
2474                         foreach (var element in source) {
2475                                 if (element.HasValue)
2476                                         total = checked (total + element.Value);
2477                         }
2478                         return total;
2479                 }
2480
2481                 public static int Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
2482                 {
2483                         Check.SourceAndSelector (source, selector);
2484                         int total = 0;
2485
2486                         foreach (var element in source)
2487                                 total = checked (total + selector (element));
2488
2489                         return total;
2490                 }
2491
2492                 public static int? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
2493                 {
2494                         Check.SourceAndSelector (source, selector);
2495
2496                         int total = 0;
2497                         foreach (var element in source) {
2498                                 var value = selector (element);
2499                                 if (value.HasValue)
2500                                         total = checked (total + value.Value);
2501                         }
2502                         return total;
2503                 }
2504
2505                 public static long Sum (this IEnumerable<long> source)
2506                 {
2507                         Check.Source (source);
2508
2509                         long total = 0;
2510                         
2511                         foreach (var element in source)
2512                                 total = checked (total + element);
2513                         return total;
2514                 }
2515
2516                 public static long? Sum (this IEnumerable<long?> source)
2517                 {
2518                         Check.Source (source);
2519
2520                         long total = 0;
2521                         foreach (var element in source) {
2522                                 if (element.HasValue)
2523                                         total = checked (total + element.Value);
2524                         }
2525                         return total;
2526                 }
2527
2528                 public static long Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
2529                 {
2530                         Check.SourceAndSelector (source, selector);
2531
2532                         long total = 0;
2533                         foreach (var element in source)
2534                                 total = checked (total + selector (element));
2535                         return total;
2536                 }
2537
2538                 public static long? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
2539                 {
2540                         Check.SourceAndSelector (source, selector);
2541
2542                         long total = 0;
2543                         foreach (var element in source) {
2544                                 var value = selector (element);
2545                                 if (value.HasValue)
2546                                         total = checked (total + value.Value);
2547                         }
2548                         return total;
2549                 }
2550
2551                 public static double Sum (this IEnumerable<double> source)
2552                 {
2553                         Check.Source (source);
2554
2555                         double total = 0;
2556                         
2557                         foreach (var element in source)
2558                                 total = checked (total + element);
2559                         return total;
2560                 }
2561
2562                 public static double? Sum (this IEnumerable<double?> source)
2563                 {
2564                         Check.Source (source);
2565
2566                         double total = 0;
2567                         foreach (var element in source) {
2568                                 if (element.HasValue)
2569                                         total = checked (total + element.Value);
2570                         }
2571                         return total;
2572                 }
2573
2574                 public static double Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
2575                 {
2576                         Check.SourceAndSelector (source, selector);
2577
2578                         double total = 0;
2579                         
2580                         foreach (var element in source)
2581                                 total = checked (total + selector (element));
2582                         return total;
2583                 }
2584
2585                 public static double? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
2586                 {
2587                         Check.SourceAndSelector (source, selector);
2588
2589                         double total = 0;
2590                         foreach (var element in source) {
2591                                 var value = selector (element);
2592                                 if (value.HasValue)
2593                                         total = checked (total + value.Value);
2594                         }
2595                         return total;
2596                 }
2597
2598                 public static float Sum (this IEnumerable<float> source)
2599                 {
2600                         Check.Source (source);
2601
2602                         float total = 0;
2603                         
2604                         foreach (var element in source)
2605                                 total = checked (total + element);
2606                         return total;
2607                 }
2608
2609                 public static float? Sum (this IEnumerable<float?> source)
2610                 {
2611                         Check.Source (source);
2612
2613                         float total = 0;
2614                         foreach (var element in source) {
2615                                 if (element.HasValue)
2616                                         total = checked (total + element.Value);
2617                         }
2618                         return total;
2619
2620                 }
2621
2622                 public static float Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
2623                 {
2624                         Check.SourceAndSelector (source, selector);
2625                         float total = 0;
2626                         foreach (var element in source)
2627                                 total = checked (total + selector (element));
2628                         return total;
2629                 }
2630
2631                 public static float? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
2632                 {
2633                         Check.SourceAndSelector (source, selector);
2634
2635                         float total = 0;
2636                         foreach (var element in source) {
2637                                 var value = selector (element);
2638                                 if (value.HasValue)
2639                                         total = checked (total + value.Value);
2640                         }
2641                         return total;
2642                 }
2643
2644                 public static decimal Sum (this IEnumerable<decimal> source)
2645                 {
2646                         Check.Source (source);
2647                         decimal total = 0;
2648                         
2649                         foreach (var element in source)
2650                                 total = checked (total + element);
2651                         return total;
2652                 }
2653
2654                 public static decimal? Sum (this IEnumerable<decimal?> source)
2655                 {
2656                         Check.Source (source);
2657
2658                         decimal total = 0;
2659                         foreach (var element in source) {
2660                                 if (element.HasValue)
2661                                         total = checked (total + element.Value);
2662                         }
2663                         return total;
2664
2665                 }
2666
2667                 public static decimal Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
2668                 {
2669                         Check.SourceAndSelector (source, selector);
2670                         decimal total = 0;
2671                         
2672                         foreach (var element in source)
2673                                 total = checked (total + selector (element));
2674                         return total;
2675                 }
2676
2677                 public static decimal? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
2678                 {
2679                         Check.SourceAndSelector (source, selector);
2680
2681                         decimal total = 0;
2682                         foreach (var element in source) {
2683                                 var value = selector (element);
2684                                 if (value.HasValue)
2685                                         total = checked (total + value.Value);
2686                         }
2687                         return total;
2688                 }
2689
2690                 #endregion
2691
2692                 #region Take
2693
2694                 public static IEnumerable<TSource> Take<TSource> (this IEnumerable<TSource> source, int count)
2695                 {
2696                         Check.Source (source);
2697
2698                         return CreateTakeIterator (source, count);
2699                 }
2700
2701                 static IEnumerable<TSource> CreateTakeIterator<TSource> (IEnumerable<TSource> source, int count)
2702                 {
2703                         if (count <= 0)
2704                                 yield break;
2705
2706                         int counter = 0;
2707                         foreach (TSource element in source) {
2708                                 yield return element;
2709
2710                                 if (++counter == count)
2711                                         yield break;
2712                         }
2713                 }
2714
2715                 #endregion
2716
2717                 #region TakeWhile
2718
2719                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2720                 {
2721                         Check.SourceAndPredicate (source, predicate);
2722
2723                         return CreateTakeWhileIterator (source, predicate);
2724                 }
2725
2726                 static IEnumerable<TSource> CreateTakeWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
2727                 {
2728                         foreach (var element in source) {
2729                                 if (!predicate (element))
2730                                         yield break;
2731
2732                                 yield return element;
2733                         }
2734                 }
2735
2736                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2737                 {
2738                         Check.SourceAndPredicate (source, predicate);
2739
2740                         return CreateTakeWhileIterator (source, predicate);
2741                 }
2742
2743                 static IEnumerable<TSource> CreateTakeWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2744                 {
2745                         int counter = 0;
2746                         foreach (var element in source) {
2747                                 if (!predicate (element, counter))
2748                                         yield break;
2749
2750                                 yield return element;
2751                                 counter++;
2752                         }
2753                 }
2754
2755                 #endregion
2756
2757                 #region ThenBy
2758
2759                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2760                 {
2761                         return ThenBy<TSource, TKey> (source, keySelector, null);
2762                 }
2763
2764                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2765                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2766                 {
2767                         Check.SourceAndKeySelector (source, keySelector);
2768
2769                         return source.CreateOrderedEnumerable (keySelector, comparer, false);
2770                 }
2771
2772                 #endregion
2773
2774                 #region ThenByDescending
2775
2776                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2777                         Func<TSource, TKey> keySelector)
2778                 {
2779                         return ThenByDescending<TSource, TKey> (source, keySelector, null);
2780                 }
2781
2782                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2783                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2784                 {
2785                         Check.SourceAndKeySelector (source, keySelector);
2786
2787                         return source.CreateOrderedEnumerable (keySelector, comparer, true);
2788                 }
2789
2790                 #endregion
2791
2792                 #region ToArray
2793
2794                 public static TSource [] ToArray<TSource> (this IEnumerable<TSource> source)
2795                 {
2796                         Check.Source (source);
2797
2798                         var collection = source as ICollection<TSource>;
2799                         if (collection != null) {
2800                                 var array = new TSource [collection.Count];
2801                                 collection.CopyTo (array, 0);
2802                                 return array;
2803                         }
2804
2805                         return new List<TSource> (source).ToArray ();
2806                 }
2807
2808                 #endregion
2809
2810                 #region ToDictionary
2811                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2812                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2813                 {
2814                         return ToDictionary<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2815                 }
2816
2817                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2818                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2819                 {
2820                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2821
2822                         if (comparer == null)
2823                                 comparer = EqualityComparer<TKey>.Default;
2824
2825                         var dict = new Dictionary<TKey, TElement> (comparer);
2826                         foreach (var e in source)
2827                                 dict.Add (keySelector (e), elementSelector (e));
2828
2829                         return dict;
2830                 }
2831
2832                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2833                                 Func<TSource, TKey> keySelector)
2834                 {
2835                         return ToDictionary (source, keySelector, null);
2836                 }
2837
2838                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2839                                 Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2840                 {
2841                         return ToDictionary<TSource, TKey, TSource> (source, keySelector, Function<TSource>.Identity, comparer);
2842                 }
2843
2844                 #endregion
2845
2846                 #region ToList
2847                 public static List<TSource> ToList<TSource> (this IEnumerable<TSource> source)
2848                 {
2849                         Check.Source (source);
2850
2851                         return new List<TSource> (source);
2852                 }
2853                 #endregion
2854
2855                 #region ToLookup
2856
2857                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2858                 {
2859                         return ToLookup<TSource, TKey, TSource> (source, keySelector, Function<TSource>.Identity, null);
2860                 }
2861
2862                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source,
2863                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2864                 {
2865                         return ToLookup<TSource, TKey, TSource> (source, keySelector, element => element, comparer);
2866                 }
2867
2868                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2869                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2870                 {
2871                         return ToLookup<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2872                 }
2873
2874                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2875                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2876                 {
2877                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2878
2879                         List<TElement> nullKeyElements = null;
2880                         
2881                         var dictionary = new Dictionary<TKey, List<TElement>> (comparer ?? EqualityComparer<TKey>.Default);
2882                         foreach (var element in source) {
2883                                 var key = keySelector (element);
2884
2885                                 List<TElement> list;
2886                                 
2887                                 if (key == null) {
2888                                         if (nullKeyElements == null)
2889                                                 nullKeyElements = new List<TElement> ();
2890                                         
2891                                         list = nullKeyElements;
2892                                 } else if (!dictionary.TryGetValue (key, out list)) {
2893                                         list = new List<TElement> ();
2894                                         dictionary.Add (key, list);
2895                                 }
2896
2897                                 list.Add (elementSelector (element));
2898                         }
2899
2900                         return new Lookup<TKey, TElement> (dictionary, nullKeyElements);
2901                 }
2902
2903                 #endregion
2904
2905                 #region SequenceEqual
2906
2907                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2908                 {
2909                         return first.SequenceEqual (second, null);
2910                 }
2911
2912                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2913                 {
2914                         Check.FirstAndSecond (first, second);
2915
2916                         if (comparer == null)
2917                                 comparer = EqualityComparer<TSource>.Default;
2918
2919                         using (IEnumerator<TSource> first_enumerator = first.GetEnumerator (),
2920                                 second_enumerator = second.GetEnumerator ()) {
2921
2922                                 while (first_enumerator.MoveNext ()) {
2923                                         if (!second_enumerator.MoveNext ())
2924                                                 return false;
2925
2926                                         if (!comparer.Equals (first_enumerator.Current, second_enumerator.Current))
2927                                                 return false;
2928                                 }
2929
2930                                 return !second_enumerator.MoveNext ();
2931                         }
2932                 }
2933
2934                 #endregion
2935
2936                 #region Union
2937
2938                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2939                 {
2940                         Check.FirstAndSecond (first, second);
2941
2942                         return first.Union (second, null);
2943                 }
2944
2945                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2946                 {
2947                         Check.FirstAndSecond (first, second);
2948
2949                         if (comparer == null)
2950                                 comparer = EqualityComparer<TSource>.Default;
2951
2952                         return CreateUnionIterator (first, second, comparer);
2953                 }
2954
2955                 static IEnumerable<TSource> CreateUnionIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2956                 {
2957                         var items = new HashSet<TSource> (comparer);
2958                         foreach (var element in first) {
2959                                 if (! items.Contains (element)) {
2960                                         items.Add (element);
2961                                         yield return element;
2962                                 }
2963                         }
2964
2965                         foreach (var element in second) {
2966                                 if (! items.Contains (element)) {
2967                                         items.Add (element);
2968                                         yield return element;
2969                                 }
2970                         }
2971                 }
2972
2973                 #endregion
2974                 
2975 #if NET_4_0 || MOONLIGHT
2976                 #region Zip
2977                 
2978                 public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult> (this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
2979                 {
2980                         Check.FirstAndSecond (first, second);
2981                         if (resultSelector == null)
2982                                 throw new ArgumentNullException ("resultSelector");
2983                                 
2984                         return CreateZipIterator (first, second, resultSelector);
2985                 }
2986                 
2987                 static IEnumerable<TResult> CreateZipIterator<TFirst, TSecond, TResult> (IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> selector)
2988                 {
2989                         using (IEnumerator<TFirst> first_enumerator = first.GetEnumerator ()) {
2990                                 using (IEnumerator<TSecond> second_enumerator = second.GetEnumerator ()) {
2991
2992                                         while (first_enumerator.MoveNext () && second_enumerator.MoveNext ()) {
2993                                                 yield return selector (first_enumerator.Current, second_enumerator.Current);
2994                                         }
2995                                 }
2996                         }
2997                 }
2998                 
2999                 #endregion
3000 #endif          
3001
3002                 #region Where
3003
3004                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
3005                 {
3006                         Check.SourceAndPredicate (source, predicate);
3007
3008                         return CreateWhereIterator (source, predicate);
3009                 }
3010
3011                 static IEnumerable<TSource> CreateWhereIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
3012                 {
3013                         foreach (TSource element in source)
3014                                 if (predicate (element))
3015                                         yield return element;
3016                 }
3017
3018                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
3019                 {
3020                         Check.SourceAndPredicate (source, predicate);
3021
3022                         return CreateWhereIterator (source, predicate);
3023                 }
3024
3025                 static IEnumerable<TSource> CreateWhereIterator<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
3026                 {
3027                         int counter = 0;
3028                         foreach (TSource element in source) {
3029                                 if (predicate (element, counter))
3030                                         yield return element;
3031                                 counter++;
3032                         }
3033                 }
3034
3035                 #endregion
3036
3037                 internal static ReadOnlyCollection<TSource> ToReadOnlyCollection<TSource> (this IEnumerable<TSource> source)
3038                 {
3039                         if (source == null)
3040                                 return ReadOnlyCollectionOf<TSource>.Empty;
3041
3042                         var ro = source as ReadOnlyCollection<TSource>;
3043                         if (ro != null)
3044                                 return ro;
3045
3046                         return new ReadOnlyCollection<TSource> (source.ToArray<TSource> ());
3047                 }
3048         }
3049 }