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