2008-02-09 Miguel de Icaza <miguel@novell.com>
[mono.git] / mcs / class / System.Core / System.Linq / Enumerable.cs
1 //
2 // Enumerable.cs
3 //
4 // Authors:
5 //  Marek Safar (marek.safar@gmail.com)
6 //  Antonello Provenzano  <antonello@deveel.com>
7 //  Alejandro Serrano "Serras" (trupill@yahoo.es)
8 //  Jb Evain (jbevain@novell.com)
9 //
10 // Copyright (C) 2007 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 // precious: http://www.hookedonlinq.com
33
34 using System;
35 using System.Collections;
36 using System.Collections.Generic;
37 using System.Collections.ObjectModel;
38
39 namespace System.Linq
40 {
41         public static class Enumerable
42         {
43                 #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) => a / b);
141                 }
142
143                 public static double Average (this IEnumerable<long> source)
144                 {
145                         return Average (source, (a, b) => a + b, (a, b) => a / 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> (Distinct (second));
675                         foreach (TSource 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
751                 public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this IEnumerable<TSource> source,
752                         Func<TSource, TKey> keySelector)
753                 {
754                         return GroupBy<TSource, TKey> (source, keySelector, null);
755                 }
756
757                 public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this IEnumerable<TSource> source,
758                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
759                 {
760                         Check.SourceAndKeySelector (source, keySelector);
761
762                         Dictionary<TKey, List<TSource>> groups = new Dictionary<TKey, List<TSource>> ();
763                         List<TSource> nullList = new List<TSource> ();
764                         int counter = 0;
765                         int nullCounter = -1;
766
767                         foreach (TSource element in source) {
768                                 TKey key = keySelector (element);
769                                 if (key == null) {
770                                         nullList.Add (element);
771                                         if (nullCounter == -1) {
772                                                 nullCounter = counter;
773                                                 counter++;
774                                         }
775                                 } else {
776                                         List<TSource> group = ContainsGroup<TKey, TSource> (groups, key, comparer);
777                                         if (group == null) {
778                                                 group = new List<TSource> ();
779                                                 groups.Add (key, group);
780                                                 counter++;
781                                         }
782                                         group.Add (element);
783                                 }
784                         }
785
786                         counter = 0;
787                         foreach (KeyValuePair<TKey, List<TSource>> group in groups) {
788                                 if (counter == nullCounter) {
789                                         Grouping<TKey, TSource> nullGroup = new Grouping<TKey, TSource> (default (TKey), nullList);
790                                         yield return nullGroup;
791                                         counter++;
792                                 }
793                                 Grouping<TKey, TSource> grouping = new Grouping<TKey, TSource> (group.Key, group.Value);
794                                 yield return grouping;
795                                 counter++;
796                         }
797                 }
798
799
800                 public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this IEnumerable<TSource> source,
801                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
802                 {
803                         return GroupBy<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
804                 }
805
806                 public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this IEnumerable<TSource> source,
807                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
808                 {
809                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
810
811                         Dictionary<TKey, List<TElement>> groups = new Dictionary<TKey, List<TElement>> ();
812                         List<TElement> nullList = new List<TElement> ();
813                         int counter = 0;
814                         int nullCounter = -1;
815
816                         foreach (TSource item in source) {
817                                 TKey key = keySelector (item);
818                                 TElement element = elementSelector (item);
819                                 if (key == null) {
820                                         nullList.Add (element);
821                                         if (nullCounter == -1) {
822                                                 nullCounter = counter;
823                                                 counter++;
824                                         }
825                                 } else {
826                                         List<TElement> group = ContainsGroup<TKey, TElement> (groups, key, comparer);
827                                         if (group == null) {
828                                                 group = new List<TElement> ();
829                                                 groups.Add (key, group);
830                                                 counter++;
831                                         }
832                                         group.Add (element);
833                                 }
834                         }
835
836                         counter = 0;
837                         foreach (KeyValuePair<TKey, List<TElement>> group in groups) {
838                                 if (counter == nullCounter) {
839                                         Grouping<TKey, TElement> nullGroup = new Grouping<TKey, TElement> (default (TKey), nullList);
840                                         yield return nullGroup;
841                                         counter++;
842                                 }
843                                 Grouping<TKey, TElement> grouping = new Grouping<TKey, TElement> (group.Key, group.Value);
844                                 yield return grouping;
845                                 counter++;
846                         }
847                 }
848
849                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult> (this IEnumerable<TSource> source,
850                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector,
851                         Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
852                 {
853                         return GroupBy (source, keySelector, elementSelector, resultSelector, null);
854                 }
855
856                 [MonoTODO]
857                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult> (this IEnumerable<TSource> source,
858                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector,
859                         Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
860                         IEqualityComparer<TKey> comparer)
861                 {
862                         throw new NotImplementedException ();
863                 }
864
865                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult> (this IEnumerable<TSource> source,
866                         Func<TSource, TKey> keySelector,
867                         Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
868                 {
869                         return GroupBy (source, keySelector, resultSelector, null);
870                 }
871
872                 [MonoTODO]
873                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult> (this IEnumerable<TSource> source,
874                         Func<TSource, TKey> keySelector,
875                         Func<TKey, IEnumerable<TSource>, TResult> resultSelector,
876                         IEqualityComparer<TKey> comparer)
877                 {
878                         throw new NotImplementedException ();
879                 }
880
881                 #endregion
882
883                 # region GroupJoin
884
885                 public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
886                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
887                         Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
888                 {
889                         return GroupJoin (outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
890                 }
891
892                 public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
893                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
894                         Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
895                         IEqualityComparer<TKey> comparer)
896                 {
897                         Check.JoinSelectors (outer, inner, outerKeySelector, innerKeySelector, resultSelector);
898
899                         if (comparer == null)
900                                 comparer = EqualityComparer<TKey>.Default;
901
902                         ILookup<TKey, TInner> innerKeys = ToLookup<TInner, TKey> (inner, innerKeySelector, comparer);
903                         /*Dictionary<K, List<U>> innerKeys = new Dictionary<K, List<U>> ();
904                         foreach (U element in inner)
905                         {
906                                         K innerKey = innerKeySelector (element);
907                                         if (!innerKeys.ContainsKey (innerKey))
908                                                         innerKeys.Add (innerKey, new List<U> ());
909                                         innerKeys[innerKey].Add (element);
910                         }*/
911
912                         foreach (TOuter element in outer) {
913                                 TKey outerKey = outerKeySelector (element);
914                                 if (innerKeys.Contains (outerKey))
915                                         yield return resultSelector (element, innerKeys [outerKey]);
916                                 else
917                                         yield return resultSelector (element, Empty<TInner> ());
918                         }
919                 }
920
921                 #endregion
922
923                 #region Intersect
924
925                 public static IEnumerable<TSource> Intersect<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
926                 {
927                         return Intersect (first, second, null);
928                 }
929
930                 public static IEnumerable<TSource> Intersect<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
931                 {
932                         Check.FirstAndSecond (first, second);
933
934                         if (comparer == null)
935                                 comparer = EqualityComparer<TSource>.Default;
936
937                         return CreateIntersectIterator (first, second, comparer);
938                 }
939
940                 static IEnumerable<TSource> CreateIntersectIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
941                 {
942                         var items = new HashSet<TSource> (second, comparer);
943                         foreach (TSource element in first) {
944                                 if (items.Contains (element))
945                                         yield return element;
946                         }
947                 }
948
949                 #endregion
950
951                 # region Join
952
953                 public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
954                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
955                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
956                 {
957                         Check.JoinSelectors (outer, inner, outerKeySelector, innerKeySelector, resultSelector);
958
959                         if (comparer == null)
960                                 comparer = EqualityComparer<TKey>.Default;
961
962                         ILookup<TKey, TInner> innerKeys = ToLookup<TInner, TKey> (inner, innerKeySelector, comparer);
963                         /*Dictionary<K, List<U>> innerKeys = new Dictionary<K, List<U>> ();
964                         foreach (U element in inner)
965                         {
966                                         K innerKey = innerKeySelector (element);
967                                         if (!innerKeys.ContainsKey (innerKey))
968                                                         innerKeys.Add (innerKey, new List<U> ());
969                                         innerKeys[innerKey].Add (element);
970                         }*/
971
972                         foreach (TOuter element in outer) {
973                                 TKey outerKey = outerKeySelector (element);
974                                 if (innerKeys.Contains (outerKey)) {
975                                         foreach (TInner innerElement in innerKeys [outerKey])
976                                                 yield return resultSelector (element, innerElement);
977                                 }
978                         }
979                 }
980
981                 public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
982                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
983                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector)
984                 {
985                         return Join<TOuter, TInner, TKey, TResult> (outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
986                 }
987
988                 # endregion
989
990                 #region Last
991
992                 public static TSource Last<TSource> (this IEnumerable<TSource> source)
993                 {
994                         Check.Source (source);
995
996                         bool noElements = true;
997                         TSource lastElement = default (TSource);
998                         foreach (TSource element in source) {
999                                 if (noElements) noElements = false;
1000                                 lastElement = element;
1001                         }
1002
1003                         if (!noElements)
1004                                 return lastElement;
1005                         else
1006                                 throw new InvalidOperationException ();
1007                 }
1008
1009                 public static TSource Last<TSource> (this IEnumerable<TSource> source,
1010                                 Func<TSource, bool> predicate)
1011                 {
1012                         Check.SourceAndPredicate (source, predicate);
1013
1014                         bool noElements = true;
1015                         TSource lastElement = default (TSource);
1016                         foreach (TSource element in source) {
1017                                 if (predicate (element)) {
1018                                         if (noElements) noElements = false;
1019                                         lastElement = element;
1020                                 }
1021                         }
1022
1023                         if (!noElements)
1024                                 return lastElement;
1025                         else
1026                                 throw new InvalidOperationException ();
1027                 }
1028
1029                 #endregion
1030
1031                 #region LastOrDefault
1032
1033                 public static TSource LastOrDefault<TSource> (this IEnumerable<TSource> source)
1034                 {
1035                         Check.Source (source);
1036
1037                         var list = source as IList<TSource>;
1038                         if (list != null)
1039                                 return list.Count > 0 ? list [list.Count - 1] : default (TSource);
1040
1041                         TSource lastElement = default (TSource);
1042                         foreach (TSource element in source)
1043                                 lastElement = element;
1044
1045                         return lastElement;
1046                 }
1047
1048                 public static TSource LastOrDefault<TSource> (this IEnumerable<TSource> source,
1049                         Func<TSource, bool> predicate)
1050                 {
1051                         Check.SourceAndPredicate (source, predicate);
1052
1053                         TSource lastElement = default (TSource);
1054                         foreach (TSource element in source) {
1055                                 if (predicate (element))
1056                                         lastElement = element;
1057                         }
1058
1059                         return lastElement;
1060                 }
1061
1062                 #endregion
1063
1064                 #region LongCount
1065                 public static long LongCount<TSource> (this IEnumerable<TSource> source)
1066                 {
1067                         Check.Source (source);
1068
1069                         long counter = 0;
1070                         using (var enumerator = source.GetEnumerator ())
1071                                 while (enumerator.MoveNext ())
1072                                         counter++;
1073
1074                         return counter;
1075                 }
1076
1077                 public static long LongCount<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> selector)
1078                 {
1079                         Check.SourceAndSelector (source, selector);
1080
1081                         long counter = 0;
1082                         foreach (TSource element in source)
1083                                 if (selector (element))
1084                                         counter++;
1085
1086                         return counter;
1087                 }
1088
1089                 #endregion
1090
1091                 #region Max
1092
1093                 public static int Max (this IEnumerable<int> source)
1094                 {
1095                         Check.Source (source);
1096
1097                         return Iterate (source, int.MinValue, (a, b) => a > b);
1098                 }
1099
1100                 public static long Max (this IEnumerable<long> source)
1101                 {
1102                         Check.Source (source);
1103
1104                         return Iterate (source, long.MinValue, (a, b) => a > b);
1105                 }
1106
1107                 public static double Max (this IEnumerable<double> source)
1108                 {
1109                         Check.Source (source);
1110
1111                         return Iterate (source, double.MinValue, (a, b) => a > b);
1112                 }
1113
1114                 public static float Max (this IEnumerable<float> source)
1115                 {
1116                         Check.Source (source);
1117
1118                         return Iterate (source, float.MinValue, (a, b) => a > b);
1119                 }
1120
1121                 public static decimal Max (this IEnumerable<decimal> source)
1122                 {
1123                         Check.Source (source);
1124
1125                         return Iterate (source, decimal.MinValue, (a, b) => a > b);
1126                 }
1127
1128                 static T Iterate<T> (IEnumerable<T> source, T initValue, Func<T, T, bool> selector)
1129                 {
1130                         int counter = 0;
1131                         foreach (var element in source) {
1132                                 if (selector (element, initValue))
1133                                         initValue = element;
1134                                 ++counter;
1135                         }
1136
1137                         if (counter == 0)
1138                                 throw new InvalidOperationException ();
1139
1140                         return initValue;
1141                 }
1142
1143                 public static int? Max (this IEnumerable<int?> source)
1144                 {
1145                         Check.Source (source);
1146
1147                         return IterateNullable (source, int.MinValue, (a, b) => a > b);
1148                 }
1149
1150                 public static long? Max (this IEnumerable<long?> source)
1151                 {
1152                         Check.Source (source);
1153
1154                         return IterateNullable (source, long.MinValue, (a, b) => a > b);
1155                 }
1156
1157                 public static double? Max (this IEnumerable<double?> source)
1158                 {
1159                         Check.Source (source);
1160
1161                         return IterateNullable (source, double.MinValue, (a, b) => a > b);
1162                 }
1163
1164                 public static float? Max (this IEnumerable<float?> source)
1165                 {
1166                         Check.Source (source);
1167
1168                         return IterateNullable (source, float.MinValue, (a, b) => a > b);
1169                 }
1170
1171                 public static decimal? Max (this IEnumerable<decimal?> source)
1172                 {
1173                         Check.Source (source);
1174
1175                         return IterateNullable (source, decimal.MinValue, (a, b) => a > b);
1176                 }
1177
1178                 static T? IterateNullable<T> (IEnumerable<T?> source, T initValue, Func<T?, T?, bool> selector) where T : struct
1179                 {
1180                         int counter = 0;
1181                         T? value = initValue;
1182                         foreach (var element in source) {
1183                                 if (!element.HasValue)
1184                                         continue;
1185
1186                                 if (selector (element.Value, value))
1187                                         value = element;
1188                                 ++counter;
1189                         }
1190
1191                         if (counter == 0)
1192                                 return null;
1193
1194                         return value;
1195                 }
1196
1197                 public static TSource Max<TSource> (this IEnumerable<TSource> source)
1198                 {
1199                         Check.Source (source);
1200
1201                         bool notAssigned = true;
1202                         TSource maximum = default (TSource);
1203                         int counter = 0;
1204                         foreach (TSource element in source) {
1205                                 if (notAssigned) {
1206                                         maximum = element;
1207                                         notAssigned = false;
1208                                 } else {
1209                                         int comparison;
1210                                         if (element is IComparable<TSource>)
1211                                                 comparison = ((IComparable<TSource>) element).CompareTo (maximum);
1212                                         else if (element is System.IComparable)
1213                                                 comparison = ((System.IComparable) element).CompareTo (maximum);
1214                                         else
1215                                                 throw new ArgumentNullException ();
1216
1217                                         if (comparison > 0)
1218                                                 maximum = element;
1219                                 }
1220                                 counter++;
1221                         }
1222
1223                         if (counter == 0)
1224                                 throw new InvalidOperationException ();
1225                         else
1226                                 return maximum;
1227                 }
1228
1229                 public static int Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1230                 {
1231                         Check.SourceAndSelector (source, selector);
1232
1233                         return Iterate (source, int.MinValue, (a, b) => {
1234                                 var v = selector (a); return v > b ? v : b;
1235                         });
1236                 }
1237
1238                 public static long Max<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1239                 {
1240                         Check.SourceAndSelector (source, selector);
1241
1242                         return Iterate (source, long.MinValue, (a, b) => {
1243                                 var v = selector (a); return v > b ? v : b;
1244                         });
1245                 }
1246
1247                 public static double Max<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1248                 {
1249                         Check.SourceAndSelector (source, selector);
1250
1251                         return Iterate (source, double.MinValue, (a, b) => {
1252                                 var v = selector (a); return v > b ? v : b;
1253                         });
1254                 }
1255
1256                 public static float Max<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1257                 {
1258                         Check.SourceAndSelector (source, selector);
1259
1260                         return Iterate (source, float.MinValue, (a, b) => {
1261                                 var v = selector (a); return v > b ? v : b;
1262                         });
1263                 }
1264
1265                 public static decimal Max<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1266                 {
1267                         Check.SourceAndSelector (source, selector);
1268
1269                         return Iterate (source, decimal.MinValue, (a, b) => {
1270                                 var v = selector (a); return v > b ? v : b;
1271                         });
1272                 }
1273
1274                 static U Iterate<T, U> (IEnumerable<T> source, U initValue, Func<T, U, U> selector)
1275                 {
1276                         int counter = 0;
1277                         foreach (var element in source) {
1278                                 initValue = selector (element, initValue);
1279                                 ++counter;
1280                         }
1281
1282                         if (counter == 0)
1283                                 throw new InvalidOperationException ();
1284
1285                         return initValue;
1286                 }
1287
1288                 static U? IterateNullable<T, U> (IEnumerable<T> source, U initialValue, Func<T, U?, U?> selector) where U : struct
1289                 {
1290                         int counter = 0;
1291                         U? value = initialValue;
1292                         foreach (var element in source) {
1293                                 value = selector (element, value);
1294                                 if (!value.HasValue)
1295                                         continue;
1296
1297                                 ++counter;
1298                         }
1299
1300                         if (counter == 0)
1301                                 return null;
1302
1303                         return value;
1304                 }
1305
1306                 public static int? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1307                 {
1308                         Check.SourceAndSelector (source, selector);
1309
1310                         return IterateNullable (source, int.MinValue, (a, b) => {
1311                                 var v = selector (a); return v > b ? v : b;
1312                         });
1313                 }
1314
1315                 public static long? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1316                 {
1317                         Check.SourceAndSelector (source, selector);
1318
1319                         return IterateNullable (source, long.MinValue, (a, b) => {
1320                                 var v = selector (a); return v > b ? v : b;
1321                         });
1322                 }
1323
1324                 public static double? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1325                 {
1326                         Check.SourceAndSelector (source, selector);
1327
1328                         return IterateNullable (source, double.MinValue, (a, b) => {
1329                                 var v = selector (a); return v > b ? v : b;
1330                         });
1331                 }
1332
1333                 public static float? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1334                 {
1335                         Check.SourceAndSelector (source, selector);
1336
1337                         return IterateNullable (source, float.MinValue, (a, b) => {
1338                                 var v = selector (a); return v > b ? v : b;
1339                         });
1340                 }
1341
1342                 public static decimal? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1343                 {
1344                         Check.SourceAndSelector (source, selector);
1345
1346                         return IterateNullable (source, decimal.MinValue, (a, b) => {
1347                                 var v = selector (a); return v > b ? v : b;
1348                         });
1349                 }
1350
1351                 public static TResult Max<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1352                 {
1353                         Check.SourceAndSelector (source, selector);
1354
1355                         bool notAssigned = true;
1356                         TResult maximum = default (TResult);
1357                         int counter = 0;
1358                         foreach (TSource item in source) {
1359                                 TResult element = selector (item);
1360                                 if (notAssigned) {
1361                                         maximum = element;
1362                                         notAssigned = false;
1363                                 } else {
1364                                         int comparison;
1365                                         if (element is IComparable<TResult>)
1366                                                 comparison = ((IComparable<TResult>) element).CompareTo (maximum);
1367                                         else if (element is System.IComparable)
1368                                                 comparison = ((System.IComparable) element).CompareTo (maximum);
1369                                         else
1370                                                 throw new ArgumentNullException ();
1371
1372                                         if (comparison > 0)
1373                                                 maximum = element;
1374                                 }
1375                                 counter++;
1376                         }
1377
1378                         if (counter == 0)
1379                                 throw new InvalidOperationException ();
1380                         else
1381                                 return maximum;
1382                 }
1383
1384                 #endregion
1385
1386                 #region Min
1387
1388                 public static int Min (this IEnumerable<int> source)
1389                 {
1390                         Check.Source (source);
1391
1392                         return Iterate (source, int.MaxValue, (a, b) => a < b);
1393                 }
1394
1395                 public static long Min (this IEnumerable<long> source)
1396                 {
1397                         Check.Source (source);
1398
1399                         return Iterate (source, long.MaxValue, (a, b) => a < b);
1400                 }
1401
1402                 public static double Min (this IEnumerable<double> source)
1403                 {
1404                         Check.Source (source);
1405
1406                         return Iterate (source, double.MaxValue, (a, b) => a < b);
1407                 }
1408
1409                 public static float Min (this IEnumerable<float> source)
1410                 {
1411                         Check.Source (source);
1412
1413                         return Iterate (source, float.MaxValue, (a, b) => a < b);
1414                 }
1415
1416                 public static decimal Min (this IEnumerable<decimal> source)
1417                 {
1418                         Check.Source (source);
1419
1420                         return Iterate (source, decimal.MaxValue, (a, b) => a < b);
1421                 }
1422
1423                 public static int? Min (this IEnumerable<int?> source)
1424                 {
1425                         Check.Source (source);
1426
1427                         return IterateNullable (source, int.MaxValue, (a, b) => a < b);
1428                 }
1429
1430                 public static long? Min (this IEnumerable<long?> source)
1431                 {
1432                         Check.Source (source);
1433
1434                         return IterateNullable (source, long.MaxValue, (a, b) => a < b);
1435                 }
1436
1437                 public static double? Min (this IEnumerable<double?> source)
1438                 {
1439                         Check.Source (source);
1440
1441                         return IterateNullable (source, double.MaxValue, (a, b) => a < b);
1442                 }
1443
1444                 public static float? Min (this IEnumerable<float?> source)
1445                 {
1446                         Check.Source (source);
1447
1448                         return IterateNullable (source, float.MaxValue, (a, b) => a < b);
1449                 }
1450
1451                 public static decimal? Min (this IEnumerable<decimal?> source)
1452                 {
1453                         Check.Source (source);
1454
1455                         return IterateNullable (source, decimal.MaxValue, (a, b) => a < b);
1456                 }
1457
1458                 public static TSource Min<TSource> (this IEnumerable<TSource> source)
1459                 {
1460                         Check.Source (source);
1461
1462                         bool notAssigned = true;
1463                         TSource minimum = default (TSource);
1464                         int counter = 0;
1465                         foreach (TSource element in source) {
1466                                 if (notAssigned) {
1467                                         minimum = element;
1468                                         notAssigned = false;
1469                                 } else {
1470                                         int comparison;
1471                                         if (element is IComparable<TSource>)
1472                                                 comparison = ((IComparable<TSource>) element).CompareTo (minimum);
1473                                         else if (element is System.IComparable)
1474                                                 comparison = ((System.IComparable) element).CompareTo (minimum);
1475                                         else
1476                                                 throw new ArgumentNullException ();
1477
1478                                         if (comparison < 0)
1479                                                 minimum = element;
1480                                 }
1481                                 counter++;
1482                         }
1483
1484                         if (counter == 0)
1485                                 throw new InvalidOperationException ();
1486                         else
1487                                 return minimum;
1488                 }
1489
1490                 public static int Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1491                 {
1492                         Check.SourceAndSelector (source, selector);
1493
1494                         return Iterate (source, int.MaxValue, (a, b) => {
1495                                 var v = selector (a); return v < b ? v : b;
1496                         });
1497                 }
1498
1499                 public static long Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1500                 {
1501                         Check.SourceAndSelector (source, selector);
1502
1503                         return Iterate (source, long.MaxValue, (a, b) => {
1504                                 var v = selector (a); return v < b ? v : b;
1505                         });
1506                 }
1507
1508                 public static double Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1509                 {
1510                         Check.SourceAndSelector (source, selector);
1511
1512                         return Iterate (source, double.MaxValue, (a, b) => {
1513                                 var v = selector (a); return v < b ? v : b;
1514                         });
1515                 }
1516
1517                 public static float Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1518                 {
1519                         Check.SourceAndSelector (source, selector);
1520
1521                         return Iterate (source, float.MaxValue, (a, b) => {
1522                                 var v = selector (a); return v < b ? v : b;
1523                         });
1524                 }
1525
1526                 public static decimal Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1527                 {
1528                         Check.SourceAndSelector (source, selector);
1529
1530                         return Iterate (source, decimal.MaxValue, (a, b) => {
1531                                 var v = selector (a); return v < b ? v : b;
1532                         });
1533                 }
1534
1535                 public static int? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1536                 {
1537                         Check.SourceAndSelector (source, selector);
1538
1539                         return IterateNullable (source, int.MaxValue, (a, b) => {
1540                                 var v = selector (a); return v < b ? v : b;
1541                         });
1542                 }
1543
1544                 public static long? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1545                 {
1546                         Check.SourceAndSelector (source, selector);
1547
1548                         return IterateNullable (source, long.MaxValue, (a, b) => {
1549                                 var v = selector (a); return v < b ? v : b;
1550                         });
1551                 }
1552
1553                 public static float? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1554                 {
1555                         Check.SourceAndSelector (source, selector);
1556
1557                         return IterateNullable (source, float.MaxValue, (a, b) => {
1558                                 var v = selector (a); return v < b ? v : b;
1559                         });
1560                 }
1561
1562                 public static double? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1563                 {
1564                         Check.SourceAndSelector (source, selector);
1565
1566                         return IterateNullable (source, double.MaxValue, (a, b) => {
1567                                 var v = selector (a); return v < b ? v : b;
1568                         });
1569                 }
1570
1571                 public static decimal? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1572                 {
1573                         Check.SourceAndSelector (source, selector);
1574
1575                         return IterateNullable (source, decimal.MaxValue, (a, b) => {
1576                                 var v = selector (a); return v < b ? v : b;
1577                         });
1578                 }
1579
1580                 public static TResult Min<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1581                 {
1582                         Check.SourceAndSelector (source, selector);
1583
1584                         bool notAssigned = true;
1585                         TResult minimum = default (TResult);
1586                         int counter = 0;
1587                         foreach (TSource item in source) {
1588                                 TResult element = selector (item);
1589                                 if (notAssigned) {
1590                                         minimum = element;
1591                                         notAssigned = false;
1592                                 } else {
1593                                         int comparison;
1594                                         if (element is IComparable<TResult>)
1595                                                 comparison = ((IComparable<TResult>) element).CompareTo (minimum);
1596                                         else if (element is System.IComparable)
1597                                                 comparison = ((System.IComparable) element).CompareTo (minimum);
1598                                         else
1599                                                 throw new ArgumentNullException ();
1600
1601                                         if (comparison < 0)
1602                                                 minimum = element;
1603                                 }
1604                                 counter++;
1605                         }
1606
1607                         if (counter == 0)
1608                                 throw new InvalidOperationException ();
1609                         else
1610                                 return minimum;
1611                 }
1612
1613                 #endregion
1614
1615                 #region OfType
1616
1617                 public static IEnumerable<TResult> OfType<TResult> (this IEnumerable source)
1618                 {
1619                         Check.Source (source);
1620
1621                         return CreateOfTypeIterator<TResult> (source);
1622                 }
1623
1624                 static IEnumerable<TResult> CreateOfTypeIterator<TResult> (IEnumerable source)
1625                 {
1626                         foreach (object element in source)
1627                                 if (element is TResult)
1628                                         yield return (TResult) element;
1629                 }
1630
1631                 #endregion
1632
1633                 #region OrderBy
1634
1635                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
1636                                 Func<TSource, TKey> keySelector)
1637                 {
1638                         return OrderBy<TSource, TKey> (source, keySelector, null);
1639                 }
1640
1641
1642                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
1643                                 Func<TSource, TKey> keySelector,
1644                                 IComparer<TKey> comparer)
1645                 {
1646                         Check.SourceAndKeySelector (source, keySelector);
1647
1648                         return new InternalOrderedSequence<TSource, TKey> (
1649                                         source, keySelector, comparer, false);
1650                 }
1651
1652                 #endregion
1653
1654                 #region OrderByDescending
1655
1656                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
1657                                 Func<TSource, TKey> keySelector)
1658                 {
1659                         return OrderByDescending<TSource, TKey> (source, keySelector, null);
1660                 }
1661
1662
1663                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
1664                                 Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
1665                 {
1666                         Check.SourceAndKeySelector (source, keySelector);
1667
1668                         return new InternalOrderedSequence<TSource, TKey> (
1669                                         source, keySelector, comparer, true);
1670                 }
1671
1672                 #endregion
1673
1674                 #region Range
1675
1676                 public static IEnumerable<int> Range (int start, int count)
1677                 {
1678                         if (count < 0)
1679                                 throw new ArgumentOutOfRangeException ("count");
1680
1681                         long upto = ((long) start + count) - 1;
1682
1683                         if (upto > int.MaxValue)
1684                                 throw new ArgumentOutOfRangeException ();
1685
1686                         return CreateRangeIterator (start, (int) upto);
1687                 }
1688
1689                 static IEnumerable<int> CreateRangeIterator (int start, int upto)
1690                 {
1691                         for (int i = start; i <= upto; i++)
1692                                 yield return i;
1693                 }
1694
1695                 #endregion
1696
1697                 #region Repeat
1698
1699                 public static IEnumerable<TResult> Repeat<TResult> (TResult element, int count)
1700                 {
1701                         if (count < 0)
1702                                 throw new ArgumentOutOfRangeException ();
1703
1704                         return CreateRepeatIterator (element, count);
1705                 }
1706
1707                 static IEnumerable<TResult> CreateRepeatIterator<TResult> (TResult element, int count)
1708                 {
1709                         for (int i = 0; i < count; i++)
1710                                 yield return element;
1711                 }
1712
1713                 #endregion
1714
1715
1716                 #region Reverse
1717
1718                 public static IEnumerable<TSource> Reverse<TSource> (this IEnumerable<TSource> source)
1719                 {
1720                         Check.Source (source);
1721
1722                         return CreateReverseIterator (source);
1723                 }
1724
1725                 static IEnumerable<TSource> CreateReverseIterator<TSource> (IEnumerable<TSource> source)
1726                 {
1727                         var list = new List<TSource> (source);
1728                         list.Reverse ();
1729                         return list;
1730                 }
1731
1732                 #endregion
1733
1734                 #region Select
1735
1736                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1737                 {
1738                         Check.SourceAndSelector (source, selector);
1739
1740                         return CreateSelectIterator (source, selector);
1741                 }
1742
1743                 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, TResult> selector)
1744                 {
1745                         foreach (TSource element in source)
1746                                 yield return selector (element);
1747                 }
1748
1749                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
1750                 {
1751                         Check.SourceAndSelector (source, selector);
1752
1753                         return CreateSelectIterator (source, selector);
1754                 }
1755
1756                 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, int, TResult> selector)
1757                 {
1758                         int counter = 0;
1759                         foreach (TSource element in source) {
1760                                 yield return selector (element, counter);
1761                                 counter++;
1762                         }
1763                 }
1764
1765                 #endregion
1766
1767                 #region SelectMany
1768
1769                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
1770                 {
1771                         Check.SourceAndSelector (source, selector);
1772
1773                         return CreateSelectManyIterator (source, selector);
1774                 }
1775
1776                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
1777                 {
1778                         foreach (TSource element in source)
1779                                 foreach (TResult item in selector (element))
1780                                         yield return item;
1781                 }
1782
1783                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
1784                 {
1785                         Check.SourceAndSelector (source, selector);
1786
1787                         return CreateSelectManyIterator (source, selector);
1788                 }
1789
1790                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
1791                 {
1792                         int counter = 0;
1793                         foreach (TSource element in source) {
1794                                 foreach (TResult item in selector (element, counter))
1795                                         yield return item;
1796                                 counter++;
1797                         }
1798                 }
1799
1800                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
1801                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1802                 {
1803                         Check.SourceAndCollectionSelectors (source, collectionSelector, selector);
1804
1805                         return CreateSelectManyIterator (source, collectionSelector, selector);
1806                 }
1807
1808                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult> (IEnumerable<TSource> source,
1809                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1810                 {
1811                         foreach (TSource element in source)
1812                                 foreach (TCollection collection in collectionSelector (element))
1813                                         yield return selector (element, collection);
1814                 }
1815
1816                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
1817                         Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1818                 {
1819                         Check.SourceAndCollectionSelectors (source, collectionSelector, selector);
1820
1821                         return CreateSelectManyIterator (source, collectionSelector, selector);
1822                 }
1823
1824                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult> (IEnumerable<TSource> source,
1825                         Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1826                 {
1827                         int counter = 0;
1828                         foreach (TSource element in source)
1829                                 foreach (TCollection collection in collectionSelector (element, counter++))
1830                                         yield return selector (element, collection);
1831                 }
1832
1833                 #endregion
1834
1835                 #region Single
1836
1837                 public static TSource Single<TSource> (this IEnumerable<TSource> source)
1838                 {
1839                         Check.Source (source);
1840
1841                         bool otherElement = false;
1842                         TSource singleElement = default (TSource);
1843                         foreach (TSource element in source) {
1844                                 if (otherElement) throw new InvalidOperationException ();
1845                                 if (!otherElement) otherElement = true;
1846                                 singleElement = element;
1847                         }
1848
1849                         if (otherElement)
1850                                 return singleElement;
1851                         else
1852                                 throw new InvalidOperationException ();
1853                 }
1854
1855
1856                 public static TSource Single<TSource> (this IEnumerable<TSource> source,
1857                                 Func<TSource, bool> predicate)
1858                 {
1859                         Check.SourceAndPredicate (source, predicate);
1860
1861                         bool otherElement = false;
1862                         TSource singleElement = default (TSource);
1863                         foreach (TSource element in source) {
1864                                 if (predicate (element)) {
1865                                         if (otherElement) throw new InvalidOperationException ();
1866                                         if (!otherElement) otherElement = true;
1867                                         singleElement = element;
1868                                 }
1869                         }
1870
1871                         if (otherElement)
1872                                 return singleElement;
1873                         else
1874                                 throw new InvalidOperationException ();
1875                 }
1876
1877                 #endregion
1878
1879                 #region SingleOrDefault
1880
1881                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source)
1882                 {
1883                         Check.Source (source);
1884
1885                         bool otherElement = false;
1886                         TSource singleElement = default (TSource);
1887                         foreach (TSource element in source) {
1888                                 if (otherElement) throw new InvalidOperationException ();
1889                                 if (!otherElement) otherElement = true;
1890                                 singleElement = element;
1891                         }
1892
1893                         return singleElement;
1894                 }
1895
1896
1897                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source,
1898                                 Func<TSource, bool> predicate)
1899                 {
1900                         Check.SourceAndPredicate (source, predicate);
1901
1902                         bool otherElement = false;
1903                         TSource singleElement = default (TSource);
1904                         foreach (TSource element in source) {
1905                                 if (predicate (element)) {
1906                                         if (otherElement) throw new InvalidOperationException ();
1907                                         if (!otherElement) otherElement = true;
1908                                         singleElement = element;
1909                                 }
1910                         }
1911
1912                         return singleElement;
1913                 }
1914
1915                 #endregion
1916
1917                 #region Skip
1918
1919                 public static IEnumerable<TSource> Skip<TSource> (this IEnumerable<TSource> source, int count)
1920                 {
1921                         Check.Source (source);
1922
1923                         return CreateSkipIterator (source, count);
1924                 }
1925
1926                 static IEnumerable<TSource> CreateSkipIterator<TSource> (IEnumerable<TSource> source, int count)
1927                 {
1928                         int i = 0;
1929                         foreach (var element in source) {
1930                                 if (i++ < count)
1931                                         continue;
1932
1933                                 yield return element;
1934                         }
1935                 }
1936
1937                 #endregion
1938
1939                 #region SkipWhile
1940
1941                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1942                 {
1943                         Check.SourceAndPredicate (source, predicate);
1944
1945                         return CreateSkipWhileIterator (source, predicate);
1946                 }
1947
1948                 static IEnumerable<TSource> CreateSkipWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
1949                 {
1950                         bool yield = false;
1951
1952                         foreach (TSource element in source) {
1953                                 if (yield)
1954                                         yield return element;
1955                                 else
1956                                         if (!predicate (element)) {
1957                                                 yield return element;
1958                                                 yield = true;
1959                                         }
1960                         }
1961                 }
1962
1963                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
1964                 {
1965                         Check.SourceAndPredicate (source, predicate);
1966
1967                         return CreateSkipWhileIterator (source, predicate);
1968                 }
1969
1970                 static IEnumerable<TSource> CreateSkipWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
1971                 {
1972                         int counter = 0;
1973                         bool yield = false;
1974
1975                         foreach (TSource element in source) {
1976                                 if (yield)
1977                                         yield return element;
1978                                 else
1979                                         if (!predicate (element, counter)) {
1980                                                 yield return element;
1981                                                 yield = true;
1982                                         }
1983                                 counter++;
1984                         }
1985                 }
1986
1987                 #endregion
1988
1989                 #region Sum
1990
1991                 public static int Sum (this IEnumerable<int> source)
1992                 {
1993                         Check.Source (source);
1994
1995                         return Sum<int, int> (source, (a, b) => a + b);
1996                 }
1997
1998                 public static int? Sum (this IEnumerable<int?> source)
1999                 {
2000                         Check.Source (source);
2001
2002                         return SumNullable<int?, int?> (source, (a, b) => a.HasValue ? a + b : a);
2003                 }
2004
2005                 public static int Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
2006                 {
2007                         Check.SourceAndSelector (source, selector);
2008
2009                         return Sum<TSource, int> (source, (a, b) => a + selector (b));
2010                 }
2011
2012                 public static int? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
2013                 {
2014                         Check.SourceAndSelector (source, selector);
2015
2016                         return SumNullable<TSource, int?> (source, (a, b) => {
2017                                 var value = selector (b);
2018                                 return value.HasValue ? a + value.Value : a;
2019                         });
2020                 }
2021
2022                 public static long Sum (this IEnumerable<long> source)
2023                 {
2024                         Check.Source (source);
2025
2026                         return Sum<long, long> (source, (a, b) => a + b);
2027                 }
2028
2029                 public static long? Sum (this IEnumerable<long?> source)
2030                 {
2031                         Check.Source (source);
2032
2033                         return SumNullable<long?, long?> (source, (a, b) => a.HasValue ? a + b : a);
2034                 }
2035
2036                 public static long Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
2037                 {
2038                         Check.SourceAndSelector (source, selector);
2039
2040                         return Sum<TSource, long> (source, (a, b) => a + selector (b));
2041                 }
2042
2043                 public static long? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
2044                 {
2045                         Check.SourceAndSelector (source, selector);
2046
2047                         return SumNullable<TSource, long?> (source, (a, b) => {
2048                                 var value = selector (b);
2049                                 return value.HasValue ? a + value.Value : a;
2050                         });
2051                 }
2052
2053                 public static double Sum (this IEnumerable<double> source)
2054                 {
2055                         Check.Source (source);
2056
2057                         return Sum<double, double> (source, (a, b) => a + b);
2058                 }
2059
2060                 public static double? Sum (this IEnumerable<double?> source)
2061                 {
2062                         Check.Source (source);
2063
2064                         return SumNullable<double?, double?> (source, (a, b) => a.HasValue ? a + b : a);
2065                 }
2066
2067                 public static double Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
2068                 {
2069                         Check.SourceAndSelector (source, selector);
2070
2071                         return Sum<TSource, double> (source, (a, b) => a + selector (b));
2072                 }
2073
2074                 public static double? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
2075                 {
2076                         Check.SourceAndSelector (source, selector);
2077
2078                         return SumNullable<TSource, double?> (source, (a, b) => {
2079                                 var value = selector (b);
2080                                 return value.HasValue ? a + value.Value : a;
2081                         });
2082                 }
2083
2084                 public static float Sum (this IEnumerable<float> source)
2085                 {
2086                         Check.Source (source);
2087
2088                         return Sum<float, float> (source, (a, b) => a + b);
2089                 }
2090
2091                 public static float? Sum (this IEnumerable<float?> source)
2092                 {
2093                         Check.Source (source);
2094
2095                         return SumNullable<float?, float?> (source, (a, b) => a.HasValue ? a + b : a);
2096                 }
2097
2098                 public static float Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
2099                 {
2100                         Check.SourceAndSelector (source, selector);
2101
2102                         return Sum<TSource, float> (source, (a, b) => a + selector (b));
2103                 }
2104
2105                 public static float? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
2106                 {
2107                         Check.SourceAndSelector (source, selector);
2108
2109                         return SumNullable<TSource, float?> (source, (a, b) => {
2110                                 var value = selector (b);
2111                                 return value.HasValue ? a + value.Value : a;
2112                         });
2113                 }
2114
2115                 public static decimal Sum (this IEnumerable<decimal> source)
2116                 {
2117                         Check.Source (source);
2118
2119                         return Sum<decimal, decimal> (source, (a, b) => a + b);
2120                 }
2121
2122                 public static decimal? Sum (this IEnumerable<decimal?> source)
2123                 {
2124                         Check.Source (source);
2125
2126                         return SumNullable<decimal?, decimal?> (source, (a, b) => a.HasValue ? a + b : a);
2127                 }
2128
2129                 public static decimal Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
2130                 {
2131                         Check.SourceAndSelector (source, selector);
2132
2133                         return Sum<TSource, decimal> (source, (a, b) => a + selector (b));
2134                 }
2135
2136                 public static decimal? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
2137                 {
2138                         Check.SourceAndSelector (source, selector);
2139
2140                         return SumNullable<TSource, decimal?> (source, (a, b) => {
2141                                 var value = selector (b);
2142                                 return value.HasValue ? a + value.Value : a;
2143                         });
2144                 }
2145
2146                 static TR Sum<TA, TR> (this IEnumerable<TA> source, Func<TR, TA, TR> selector)
2147                 {
2148                         TR total = default (TR);
2149                         int counter = 0;
2150                         foreach (var element in source) {
2151                                 total = selector (total, element);
2152                                 ++counter;
2153                         }
2154
2155                         if (counter == 0)
2156                                 throw new InvalidOperationException ();
2157
2158                         return total;
2159                 }
2160
2161                 static TR SumNullable<TA, TR> (this IEnumerable<TA> source, Func<TR, TA, TR> selector)
2162                 {
2163                         TR total = default (TR);
2164                         foreach (var element in source) {
2165                                 total = selector (total, element);
2166                         }
2167
2168                         return total;
2169                 }
2170
2171                 #endregion
2172
2173                 #region Take
2174
2175                 public static IEnumerable<TSource> Take<TSource> (this IEnumerable<TSource> source, int count)
2176                 {
2177                         Check.Source (source);
2178
2179                         return CreateTakeIterator (source, count);
2180                 }
2181
2182                 static IEnumerable<TSource> CreateTakeIterator<TSource> (IEnumerable<TSource> source, int count)
2183                 {
2184                         if (count <= 0)
2185                                 yield break;
2186
2187                         int counter = 0;
2188                         foreach (TSource element in source) {
2189                                 if (counter++ == count)
2190                                         yield break;
2191
2192                                 yield return element;
2193                         }
2194                 }
2195
2196                 #endregion
2197
2198                 #region TakeWhile
2199
2200                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2201                 {
2202                         Check.SourceAndPredicate (source, predicate);
2203
2204                         return CreateTakeWhileIterator (source, predicate);
2205                 }
2206
2207                 static IEnumerable<TSource> CreateTakeWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
2208                 {
2209                         foreach (TSource element in source) {
2210                                 if (!predicate (element))
2211                                         yield break;
2212
2213                                 yield return element;
2214                         }
2215                 }
2216
2217                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2218                 {
2219                         Check.SourceAndPredicate (source, predicate);
2220
2221                         return CreateTakeWhileIterator (source, predicate);
2222                 }
2223
2224                 static IEnumerable<TSource> CreateTakeWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2225                 {
2226                         int counter = 0;
2227                         foreach (var element in source) {
2228                                 if (!predicate (element, counter))
2229                                         yield break;
2230
2231                                 yield return element;
2232                                 counter++;
2233                         }
2234                 }
2235
2236                 #endregion
2237
2238                 #region ThenBy
2239
2240                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2241                 {
2242                         return ThenBy<TSource, TKey> (source, keySelector, null);
2243                 }
2244
2245
2246                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2247                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2248                 {
2249                         Check.SourceAndKeySelector (source, keySelector);
2250
2251                         return source.CreateOrderedEnumerable (keySelector, comparer, false);
2252                 }
2253
2254                 #endregion
2255
2256                 #region ThenByDescending
2257
2258                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2259                         Func<TSource, TKey> keySelector)
2260                 {
2261                         return ThenByDescending<TSource, TKey> (source, keySelector, null);
2262                 }
2263
2264
2265                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2266                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2267                 {
2268                         Check.SourceAndKeySelector (source, keySelector);
2269
2270                         return source.CreateOrderedEnumerable (keySelector, comparer, true);
2271                 }
2272
2273                 #endregion
2274
2275                 #region ToArray
2276                 public static TSource [] ToArray<TSource> (this IEnumerable<TSource> source)
2277                 {
2278                         Check.Source (source);
2279
2280                         List<TSource> list = new List<TSource> (source);
2281                         return list.ToArray ();
2282                 }
2283
2284                 #endregion
2285
2286                 #region ToDictionary
2287                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2288                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2289                 {
2290                         return ToDictionary<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2291                 }
2292
2293                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2294                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2295                 {
2296                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2297
2298                         if (comparer == null)
2299                                 comparer = EqualityComparer<TKey>.Default;
2300
2301                         var dict = new Dictionary<TKey, TElement> (comparer);
2302                         foreach (var e in source)
2303                                 dict.Add (keySelector (e), elementSelector (e));
2304
2305                         return dict;
2306                 }
2307
2308                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2309                                 Func<TSource, TKey> keySelector)
2310                 {
2311                         return ToDictionary (source, keySelector, null);
2312                 }
2313
2314                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2315                                 Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2316                 {
2317                         Check.SourceAndKeySelector (source, keySelector);
2318
2319                         if (comparer == null)
2320                                 comparer = EqualityComparer<TKey>.Default;
2321                         
2322                         var dict = new Dictionary<TKey, TSource> (comparer);
2323                         foreach (var e in source)
2324                                 dict.Add (keySelector (e), e);
2325
2326                         return dict;
2327                 }
2328
2329                 #endregion
2330
2331                 #region ToList
2332                 public static List<TSource> ToList<TSource> (this IEnumerable<TSource> source)
2333                 {
2334                         Check.Source (source);
2335
2336                         return new List<TSource> (source);
2337                 }
2338                 #endregion
2339
2340                 #region ToLookup
2341
2342                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2343                 {
2344                         return ToLookup<TSource, TKey> (source, keySelector, null);
2345                 }
2346
2347                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source,
2348                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2349                 {
2350                         Check.SourceAndKeySelector (source, keySelector);
2351
2352                         var dictionary = new Dictionary<TKey, List<TSource>> (comparer ?? EqualityComparer<TKey>.Default);
2353                         foreach (TSource element in source) {
2354                                 TKey key = keySelector (element);
2355                                 if (key == null)
2356                                         throw new ArgumentNullException ();
2357                                 if (!dictionary.ContainsKey (key))
2358                                         dictionary.Add (key, new List<TSource> ());
2359                                 dictionary [key].Add (element);
2360                         }
2361                         return new Lookup<TKey, TSource> (dictionary);
2362                 }
2363
2364                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2365                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2366                 {
2367                         return ToLookup<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2368                 }
2369
2370                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2371                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2372                 {
2373                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2374
2375                         Dictionary<TKey, List<TElement>> dictionary = new Dictionary<TKey, List<TElement>> (comparer ?? EqualityComparer<TKey>.Default);
2376                         foreach (TSource element in source) {
2377                                 TKey key = keySelector (element);
2378                                 if (key == null)
2379                                         throw new ArgumentNullException ();
2380                                 if (!dictionary.ContainsKey (key))
2381                                         dictionary.Add (key, new List<TElement> ());
2382                                 dictionary [key].Add (elementSelector (element));
2383                         }
2384                         return new Lookup<TKey, TElement> (dictionary);
2385                 }
2386
2387                 #endregion
2388
2389                 #region SequenceEqual
2390
2391                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2392                 {
2393                         return first.SequenceEqual (second, null);
2394                 }
2395
2396                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2397                 {
2398                         Check.FirstAndSecond (first, second);
2399
2400                         if (comparer == null)
2401                                 comparer = EqualityComparer<TSource>.Default;
2402
2403                         var first_enumerator = first.GetEnumerator ();
2404                         var second_enumerator = second.GetEnumerator ();
2405
2406                         while (first_enumerator.MoveNext ()) {
2407                                 if (!second_enumerator.MoveNext ())
2408                                         return false;
2409
2410                                 if (!comparer.Equals (first_enumerator.Current, second_enumerator.Current))
2411                                         return false;
2412                         }
2413
2414                         return !second_enumerator.MoveNext ();
2415                 }
2416
2417                 #endregion
2418
2419                 #region Union
2420
2421                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2422                 {
2423                         Check.FirstAndSecond (first, second);
2424
2425                         return first.Union (second, null);
2426                 }
2427
2428                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2429                 {
2430                         Check.FirstAndSecond (first, second);
2431
2432                         if (comparer == null)
2433                                 comparer = EqualityComparer<TSource>.Default;
2434
2435                         return CreateUnionIterator (first, second, comparer);
2436                 }
2437
2438                 static IEnumerable<TSource> CreateUnionIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2439                 {
2440                         var items = new HashSet<TSource> (comparer);
2441                         foreach (var element in first) {
2442                                 if (! items.Contains (element)) {
2443                                         items.Add (element);
2444                                         yield return element;
2445                                 }
2446                         }
2447
2448                         foreach (var element in second) {
2449                                 if (! items.Contains (element, comparer)) {
2450                                         items.Add (element);
2451                                         yield return element;
2452                                 }
2453                         }
2454                 }
2455
2456                 #endregion
2457
2458                 #region Where
2459
2460                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2461                 {
2462                         Check.SourceAndPredicate (source, predicate);
2463
2464                         return CreateWhereIterator (source, predicate);
2465                 }
2466
2467                 static IEnumerable<TSource> CreateWhereIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
2468                 {
2469                         foreach (TSource element in source)
2470                                 if (predicate (element))
2471                                         yield return element;
2472                 }
2473
2474                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2475                 {
2476                         Check.SourceAndPredicate (source, predicate);
2477
2478                         return CreateWhereIterator (source, predicate);
2479                 }
2480
2481                 static IEnumerable<TSource> CreateWhereIterator<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2482                 {
2483                         int counter = 0;
2484                         foreach (TSource element in source) {
2485                                 if (predicate (element, counter))
2486                                         yield return element;
2487                                 counter++;
2488                         }
2489                 }
2490
2491                 #endregion
2492
2493                 internal static ReadOnlyCollection<TSource> ToReadOnlyCollection<TSource> (this IEnumerable<TSource> source)
2494                 {
2495                         if (source == null)
2496                                 return new ReadOnlyCollection<TSource> (new TSource [0]); // could we singlotenize that?
2497
2498                         var ro = source as ReadOnlyCollection<TSource>;
2499                         if (ro != null)
2500                                 return ro;
2501
2502                         return new ReadOnlyCollection<TSource> (source.ToArray<TSource> ());
2503                 }
2504         }
2505 }