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