2007-12-04 Marek Safar <marek.safar@gmail.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                         CheckSourceAndFunc (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                         CheckSourceAndFunc (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                         CheckSourceAndFunc (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                         CheckSourceAndPredicate (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                         CheckSource (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                         CheckSourceAndPredicate (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                         CheckSource (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                         CheckSource (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                         CheckSource (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                         CheckSource (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                         CheckSource (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                         CheckSource (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                         CheckSourceAndSelector (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                         CheckSourceAndSelector (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                         CheckSourceAndSelector (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                         CheckSourceAndSelector (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                         CheckSourceAndSelector (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                         CheckSourceAndSelector (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                         CheckSourceAndSelector (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                         CheckSourceAndSelector (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                         CheckSourceAndSelector (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                         CheckSourceAndSelector (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                         CheckSource (source);
450
451                         foreach (object element in source)
452                                 yield return (TResult) element;
453                 }
454
455                 #endregion
456
457                 #region Concat
458
459                 public static IEnumerable<TSource> Concat<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
460                 {
461                         CheckFirstAndSecond (first, second);
462
463                         foreach (TSource element in first)
464                                 yield return element;
465                         foreach (TSource element in second)
466                                 yield return element;
467                 }
468
469                 #endregion
470
471                 #region Contains
472
473                 public static bool Contains<TSource> (this IEnumerable<TSource> source, TSource value)
474                 {
475                         var collection = source as ICollection<TSource>;
476                         if (collection != null)
477                                 return collection.Contains (value);
478
479                         return Contains<TSource> (source, value, null);
480                 }
481
482                 public static bool Contains<TSource> (this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
483                 {
484                         CheckSource (source);
485
486                         if (comparer == null)
487                                 comparer = EqualityComparer<TSource>.Default;
488
489                         foreach (TSource e in source) {
490                                 if (comparer.Equals (e, value))
491                                         return true;
492                         }
493
494                         return false;
495                 }
496                 #endregion
497
498                 #region Count
499
500                 public static int Count<TSource> (this IEnumerable<TSource> source)
501                 {
502                         CheckSource (source);
503
504                         var collection = source as ICollection<TSource>;
505                         if (collection != null)
506                                 return collection.Count;
507
508                         int counter = 0;
509                         using (var enumerator = source.GetEnumerator ())
510                                 while (enumerator.MoveNext ())
511                                         counter++;
512
513                         return counter;
514                 }
515
516                 public static int Count<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> selector)
517                 {
518                         CheckSourceAndSelector (source, selector);
519
520                         int counter = 0;
521                         foreach (var element in source)
522                                 if (selector (element))
523                                         counter++;
524
525                         return counter;
526                 }
527
528                 #endregion
529
530                 #region DefaultIfEmpty
531
532                 public static IEnumerable<TSource> DefaultIfEmpty<TSource> (this IEnumerable<TSource> source)
533                 {
534                         return DefaultIfEmpty (source, default (TSource));
535                 }
536
537                 public static IEnumerable<TSource> DefaultIfEmpty<TSource> (this IEnumerable<TSource> source, TSource defaultValue)
538                 {
539                         CheckSource (source);
540
541                         bool empty = true;
542                         foreach (TSource item in source) {
543                                 empty = false;
544                                 yield return item;
545                         }
546
547                         if (empty)
548                                 yield return defaultValue;
549                 }
550
551                 #endregion
552
553                 #region Distinct
554
555                 public static IEnumerable<TSource> Distinct<TSource> (this IEnumerable<TSource> source)
556                 {
557                         return Distinct<TSource> (source, null);
558                 }
559
560                 public static IEnumerable<TSource> Distinct<TSource> (this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
561                 {
562                         CheckSource (source);
563
564                         if (comparer == null)
565                                 comparer = EqualityComparer<TSource>.Default;
566
567                         var items = new List<TSource> (); // TODO: use a HashSet here
568                         foreach (var element in source) {
569                                 if (! items.Contains (element, comparer)) {
570                                         items.Add (element);
571                                         yield return element;
572                                 }
573                         }
574                 }
575
576                 #endregion
577
578                 #region ElementAt
579
580                 public static TSource ElementAt<TSource> (this IEnumerable<TSource> source, int index)
581                 {
582                         CheckSource (source);
583                         if (index < 0)
584                                 throw new ArgumentOutOfRangeException ();
585
586                         var list = source as IList<TSource>;
587                         if (list != null)
588                                 return list [index];
589
590                         int counter = 0;
591                         foreach (var element in source) {
592                                 if (counter == index)
593                                         return element;
594                                 counter++;
595                         }
596
597                         throw new ArgumentOutOfRangeException ();
598                 }
599
600                 #endregion
601
602                 #region ElementAtOrDefault
603
604                 public static TSource ElementAtOrDefault<TSource> (this IEnumerable<TSource> source, int index)
605                 {
606                         CheckSource (source);
607                         if (index < 0)
608                                 return default (TSource);
609
610                         var list = source as IList<TSource>;
611                         if (list != null)
612                                 return index < list.Count ? list [index] : default (TSource);
613
614                         int counter = 0;
615                         foreach (TSource element in source) {
616                                 if (counter == index)
617                                         return element;
618                                 counter++;
619                         }
620
621                         return default (TSource);
622                 }
623
624                 #endregion
625
626                 #region Empty
627
628                 public static IEnumerable<TResult> Empty<TResult> ()
629                 {
630                         return new TResult [0];
631                 }
632
633                 #endregion
634
635                 #region Except
636
637                 public static IEnumerable<TSource> Except<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
638                 {
639                         return Except (first, second, null);
640                 }
641
642                 public static IEnumerable<TSource> Except<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
643                 {
644                         CheckFirstAndSecond (first, second);
645
646                         if (comparer == null)
647                                 comparer = EqualityComparer<TSource>.Default;
648
649                         var items = new List<TSource> (Distinct (second));
650                         foreach (TSource element in first) {
651                                 if (! items.Contains (element, comparer))
652                                         yield return element;
653                         }
654                 }
655
656                 #endregion
657
658                 #region First
659
660                 public static TSource First<TSource> (this IEnumerable<TSource> source)
661                 {
662                         CheckSource (source);
663
664                         foreach (TSource element in source)
665                                 return element;
666
667                         throw new InvalidOperationException ();
668                 }
669
670
671                 public static TSource First<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
672                 {
673                         CheckSourceAndPredicate (source, predicate);
674
675                         foreach (TSource element in source) {
676                                 if (predicate (element))
677                                         return element;
678                         }
679
680                         throw new InvalidOperationException ();
681                 }
682
683                 #endregion
684
685                 #region FirstOrDefault
686
687                 public static TSource FirstOrDefault<TSource> (this IEnumerable<TSource> source)
688                 {
689                         CheckSource (source);
690
691                         foreach (TSource element in source)
692                                 return element;
693
694                         return default (TSource);
695                 }
696
697
698                 public static TSource FirstOrDefault<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
699                 {
700                         CheckSourceAndPredicate (source, predicate);
701
702                         foreach (TSource element in source) {
703                                 if (predicate (element))
704                                         return element;
705                         }
706
707                         return default (TSource);
708                 }
709
710                 #endregion
711
712                 #region GroupBy
713
714                 private static List<T> ContainsGroup<K, T> (
715                                 Dictionary<K, List<T>> items, K key, IEqualityComparer<K> comparer)
716                 {
717                         IEqualityComparer<K> comparerInUse = (comparer ?? EqualityComparer<K>.Default);
718                         foreach (KeyValuePair<K, List<T>> value in items) {
719                                 if (comparerInUse.Equals (value.Key, key))
720                                         return value.Value;
721                         }
722                         return null;
723                 }
724
725
726                 public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this IEnumerable<TSource> source,
727                         Func<TSource, TKey> keySelector)
728                 {
729                         return GroupBy<TSource, TKey> (source, keySelector, null);
730                 }
731
732                 public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this IEnumerable<TSource> source,
733                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
734                 {
735                         CheckSourceAndKeySelector (source, keySelector);
736
737                         Dictionary<TKey, List<TSource>> groups = new Dictionary<TKey, List<TSource>> ();
738                         List<TSource> nullList = new List<TSource> ();
739                         int counter = 0;
740                         int nullCounter = -1;
741
742                         foreach (TSource element in source) {
743                                 TKey key = keySelector (element);
744                                 if (key == null) {
745                                         nullList.Add (element);
746                                         if (nullCounter == -1) {
747                                                 nullCounter = counter;
748                                                 counter++;
749                                         }
750                                 } else {
751                                         List<TSource> group = ContainsGroup<TKey, TSource> (groups, key, comparer);
752                                         if (group == null) {
753                                                 group = new List<TSource> ();
754                                                 groups.Add (key, group);
755                                                 counter++;
756                                         }
757                                         group.Add (element);
758                                 }
759                         }
760
761                         counter = 0;
762                         foreach (KeyValuePair<TKey, List<TSource>> group in groups) {
763                                 if (counter == nullCounter) {
764                                         Grouping<TKey, TSource> nullGroup = new Grouping<TKey, TSource> (default (TKey), nullList);
765                                         yield return nullGroup;
766                                         counter++;
767                                 }
768                                 Grouping<TKey, TSource> grouping = new Grouping<TKey, TSource> (group.Key, group.Value);
769                                 yield return grouping;
770                                 counter++;
771                         }
772                 }
773
774
775                 public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this IEnumerable<TSource> source,
776                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
777                 {
778                         return GroupBy<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
779                 }
780
781                 public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this IEnumerable<TSource> source,
782                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
783                 {
784                         CheckSourceAndKeyElementSelectors (source, keySelector, elementSelector);
785
786                         Dictionary<TKey, List<TElement>> groups = new Dictionary<TKey, List<TElement>> ();
787                         List<TElement> nullList = new List<TElement> ();
788                         int counter = 0;
789                         int nullCounter = -1;
790
791                         foreach (TSource item in source) {
792                                 TKey key = keySelector (item);
793                                 TElement element = elementSelector (item);
794                                 if (key == null) {
795                                         nullList.Add (element);
796                                         if (nullCounter == -1) {
797                                                 nullCounter = counter;
798                                                 counter++;
799                                         }
800                                 } else {
801                                         List<TElement> group = ContainsGroup<TKey, TElement> (groups, key, comparer);
802                                         if (group == null) {
803                                                 group = new List<TElement> ();
804                                                 groups.Add (key, group);
805                                                 counter++;
806                                         }
807                                         group.Add (element);
808                                 }
809                         }
810
811                         counter = 0;
812                         foreach (KeyValuePair<TKey, List<TElement>> group in groups) {
813                                 if (counter == nullCounter) {
814                                         Grouping<TKey, TElement> nullGroup = new Grouping<TKey, TElement> (default (TKey), nullList);
815                                         yield return nullGroup;
816                                         counter++;
817                                 }
818                                 Grouping<TKey, TElement> grouping = new Grouping<TKey, TElement> (group.Key, group.Value);
819                                 yield return grouping;
820                                 counter++;
821                         }
822                 }
823                 
824                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult> (this IEnumerable<TSource> source,
825                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector,
826                         Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
827                 {
828                         return GroupBy (source, keySelector, elementSelector, resultSelector, null);
829                 }
830
831                 [MonoTODO]
832                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult> (this IEnumerable<TSource> source,
833                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector,
834                         Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
835                         IEqualityComparer<TKey> comparer)
836                 {
837                         throw new NotImplementedException ();
838                 }
839
840                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult> (this IEnumerable<TSource> source,
841                         Func<TSource, TKey> keySelector,
842                         Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
843                 {
844                         return GroupBy (source, keySelector, resultSelector, null);
845                 }
846
847                 [MonoTODO]              
848                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult> (this IEnumerable<TSource> source,
849                         Func<TSource, TKey> keySelector,
850                         Func<TKey, IEnumerable<TSource>, TResult> resultSelector,
851                         IEqualityComparer<TKey> comparer)                                                                                   
852                 {
853                         throw new NotImplementedException ();
854                 }
855                 
856                 #endregion
857
858                 # region GroupJoin
859
860                 public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
861                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
862                         Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
863                 {
864                         return GroupJoin (outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
865                 }
866
867                 public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
868                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
869                         Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
870                         IEqualityComparer<TKey> comparer)
871                 {
872                         CheckJoinSelectors (outer, inner, outerKeySelector, innerKeySelector, resultSelector);
873
874                         if (comparer == null)
875                                 comparer = EqualityComparer<TKey>.Default;
876
877                         ILookup<TKey, TInner> innerKeys = ToLookup<TInner, TKey> (inner, innerKeySelector, comparer);
878                         /*Dictionary<K, List<U>> innerKeys = new Dictionary<K, List<U>> ();
879                         foreach (U element in inner)
880                         {
881                                         K innerKey = innerKeySelector (element);
882                                         if (!innerKeys.ContainsKey (innerKey))
883                                                         innerKeys.Add (innerKey, new List<U> ());
884                                         innerKeys[innerKey].Add (element);
885                         }*/
886
887                         foreach (TOuter element in outer) {
888                                 TKey outerKey = outerKeySelector (element);
889                                 if (innerKeys.Contains (outerKey))
890                                         yield return resultSelector (element, innerKeys [outerKey]);
891                                 else
892                                         yield return resultSelector (element, Empty<TInner> ());
893                         }       
894                 }
895
896                 #endregion
897
898                 #region Intersect
899
900                 public static IEnumerable<TSource> Intersect<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
901                 {
902                         return Intersect (first, second, null);
903                 }
904
905                 public static IEnumerable<TSource> Intersect<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
906                 {
907                         CheckFirstAndSecond (first, second);
908
909                         if (comparer == null)
910                                 comparer = EqualityComparer<TSource>.Default;
911
912                         List<TSource> items = new List<TSource> (Distinct (first));
913                         foreach (TSource element in second) {
914                                 if (items.Contains (element, comparer))
915                                         yield return element;
916                         }
917                 }
918
919                 #endregion
920
921                 # region Join
922
923                 public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
924                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
925                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
926                 {
927                         CheckJoinSelectors (outer, inner, outerKeySelector, innerKeySelector, resultSelector);
928
929                         if (comparer == null)
930                                 comparer = EqualityComparer<TKey>.Default;
931
932                         ILookup<TKey, TInner> innerKeys = ToLookup<TInner, TKey> (inner, innerKeySelector, comparer);
933                         /*Dictionary<K, List<U>> innerKeys = new Dictionary<K, List<U>> ();
934                         foreach (U element in inner)
935                         {
936                                         K innerKey = innerKeySelector (element);
937                                         if (!innerKeys.ContainsKey (innerKey))
938                                                         innerKeys.Add (innerKey, new List<U> ());
939                                         innerKeys[innerKey].Add (element);
940                         }*/
941
942                         foreach (TOuter element in outer) {
943                                 TKey outerKey = outerKeySelector (element);
944                                 if (innerKeys.Contains (outerKey)) {
945                                         foreach (TInner innerElement in innerKeys [outerKey])
946                                                 yield return resultSelector (element, innerElement);
947                                 }
948                         }
949                 }
950
951                 public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
952                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
953                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector)
954                 {
955                         return Join<TOuter, TInner, TKey, TResult> (outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
956                 }
957
958                 # endregion
959
960                 #region Last
961
962                 public static TSource Last<TSource> (this IEnumerable<TSource> source)
963                 {
964                         CheckSource (source);
965
966                         bool noElements = true;
967                         TSource lastElement = default (TSource);
968                         foreach (TSource element in source) {
969                                 if (noElements) noElements = false;
970                                 lastElement = element;
971                         }
972
973                         if (!noElements)
974                                 return lastElement;
975                         else
976                                 throw new InvalidOperationException ();
977                 }
978
979                 public static TSource Last<TSource> (this IEnumerable<TSource> source,
980                                 Func<TSource, bool> predicate)
981                 {
982                         CheckSourceAndPredicate (source, predicate);
983
984                         bool noElements = true;
985                         TSource lastElement = default (TSource);
986                         foreach (TSource element in source) {
987                                 if (predicate (element)) {
988                                         if (noElements) noElements = false;
989                                         lastElement = element;
990                                 }
991                         }
992
993                         if (!noElements)
994                                 return lastElement;
995                         else
996                                 throw new InvalidOperationException ();
997                 }
998
999                 #endregion
1000
1001                 #region LastOrDefault
1002
1003                 public static TSource LastOrDefault<TSource> (this IEnumerable<TSource> source)
1004                 {
1005                         CheckSource (source);
1006
1007                         var list = source as IList<TSource>;
1008                         if (list != null)
1009                                 return list.Count > 0 ? list [list.Count - 1] : default (TSource);
1010
1011                         TSource lastElement = default (TSource);
1012                         foreach (TSource element in source)
1013                                 lastElement = element;
1014
1015                         return lastElement;
1016                 }
1017
1018                 public static TSource LastOrDefault<TSource> (this IEnumerable<TSource> source,
1019                         Func<TSource, bool> predicate)
1020                 {
1021                         CheckSourceAndPredicate (source, predicate);
1022
1023                         TSource lastElement = default (TSource);
1024                         foreach (TSource element in source) {
1025                                 if (predicate (element))
1026                                         lastElement = element;
1027                         }
1028
1029                         return lastElement;
1030                 }
1031
1032                 #endregion
1033
1034                 #region LongCount
1035                 public static long LongCount<TSource> (this IEnumerable<TSource> source)
1036                 {
1037                         CheckSource (source);
1038
1039                         long counter = 0;
1040                         using (var enumerator = source.GetEnumerator ())
1041                                 while (enumerator.MoveNext ())
1042                                         counter++;
1043
1044                         return counter;
1045                 }
1046
1047                 public static long LongCount<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> selector)
1048                 {
1049                         CheckSourceAndSelector (source, selector);
1050
1051                         long counter = 0;
1052                         foreach (TSource element in source)
1053                                 if (selector (element))
1054                                         counter++;
1055
1056                         return counter;
1057                 }
1058
1059                 #endregion
1060
1061                 #region Max
1062
1063                 public static int Max (this IEnumerable<int> source)
1064                 {
1065                         return Iterate (source, int.MinValue, (a, b) => a > b);
1066                 }
1067                 
1068                 public static long Max (this IEnumerable<long> source)
1069                 {
1070                         return Iterate (source, long.MinValue, (a, b) => a > b);
1071                 }
1072                 
1073                 public static double Max (this IEnumerable<double> source)
1074                 {
1075                         return Iterate (source, double.MinValue, (a, b) => a > b);
1076                 }
1077
1078                 public static float Max (this IEnumerable<float> source)
1079                 {
1080                         return Iterate (source, float.MinValue, (a, b) => a > b);
1081                 }
1082
1083                 public static decimal Max (this IEnumerable<decimal> source)
1084                 {
1085                         return Iterate (source, decimal.MinValue, (a, b) => a > b);
1086                 }
1087
1088                 static T Iterate<T> (IEnumerable<T> source, T initValue, Func<T, T, bool> selector)
1089                 {
1090                         CheckSource (source);
1091                         
1092                         int counter = 0;
1093                         foreach (var element in source) {
1094                                 if (selector (element, initValue))
1095                                         initValue = element;
1096                                 ++counter;
1097                         }
1098
1099                         if (counter == 0)
1100                                 throw new InvalidOperationException ();
1101                         
1102                         return initValue;
1103                 }
1104
1105                 public static int? Max (this IEnumerable<int?> source)
1106                 {
1107                         return IterateNullable (source, int.MinValue, (a, b) => a > b);
1108                 }
1109
1110                 public static long? Max (this IEnumerable<long?> source)
1111                 {
1112                         return IterateNullable (source, long.MinValue, (a, b) => a > b);
1113                 }
1114                 
1115                 public static double? Max (this IEnumerable<double?> source)
1116                 {
1117                         return IterateNullable (source, double.MinValue, (a, b) => a > b);
1118                 }
1119
1120                 public static float? Max (this IEnumerable<float?> source)
1121                 {
1122                         return IterateNullable (source, float.MinValue, (a, b) => a > b);
1123                 }
1124
1125                 public static decimal? Max (this IEnumerable<decimal?> source)
1126                 {
1127                         return IterateNullable (source, decimal.MinValue, (a, b) => a > b);
1128                 }               
1129
1130                 static T? IterateNullable<T> (IEnumerable<T?> source, T? initValue, Func<T?, T?, bool> selector) where T : struct
1131                 {
1132                         CheckSource (source);
1133                         
1134                         int counter = 0;
1135                         foreach (var element in source) {
1136                                 if (!element.HasValue)
1137                                         continue;
1138
1139                                 if (selector (element.Value, initValue))
1140                                         initValue = element;
1141                                 ++counter;
1142                         }
1143
1144                         if (counter == 0)
1145                                 return null;
1146                         
1147                         return initValue;
1148                 }
1149
1150                 public static TSource Max<TSource> (this IEnumerable<TSource> source)
1151                 {
1152                         CheckSource (source);
1153
1154                         bool notAssigned = true;
1155                         TSource maximum = default (TSource);
1156                         int counter = 0;
1157                         foreach (TSource element in source) {
1158                                 if (notAssigned) {
1159                                         maximum = element;
1160                                         notAssigned = false;
1161                                 } else {
1162                                         int comparison;
1163                                         if (element is IComparable<TSource>)
1164                                                 comparison = ((IComparable<TSource>) element).CompareTo (maximum);
1165                                         else if (element is System.IComparable)
1166                                                 comparison = ((System.IComparable) element).CompareTo (maximum);
1167                                         else
1168                                                 throw new ArgumentNullException ();
1169
1170                                         if (comparison > 0)
1171                                                 maximum = element;
1172                                 }
1173                                 counter++;
1174                         }
1175
1176                         if (counter == 0)
1177                                 throw new InvalidOperationException ();
1178                         else
1179                                 return maximum;
1180                 }
1181
1182                 public static int Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1183                 {
1184                         return Iterate (source, int.MinValue, (a, b) => { 
1185                                 var v = selector (a); return v > b ? v : b;
1186                         });
1187                 }
1188                 
1189                 public static long Max<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1190                 {
1191                         return Iterate (source, long.MinValue, (a, b) => { 
1192                                 var v = selector (a); return v > b ? v : b;
1193                         });
1194                 }
1195
1196                 public static double Max<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1197                 {
1198                         return Iterate (source, double.MinValue, (a, b) => { 
1199                                 var v = selector (a); return v > b ? v : b;
1200                         });
1201                 }
1202                 
1203                 public static float Max<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1204                 {
1205                         return Iterate (source, float.MinValue, (a, b) => { 
1206                                 var v = selector (a); return v > b ? v : b;
1207                         });
1208                 }
1209                 
1210                 public static decimal Max<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1211                 {
1212                         return Iterate (source, decimal.MinValue, (a, b) => { 
1213                                 var v = selector (a); return v > b ? v : b;
1214                         });
1215                 }               
1216                 
1217                 static U Iterate<T, U> (IEnumerable<T> source, U initValue, Func<T, U, U> selector)
1218                 {
1219                         CheckSourceAndSelector (source, selector);
1220                         
1221                         int counter = 0;
1222                         foreach (var element in source) {
1223                                 initValue = selector (element, initValue);
1224                                 ++counter;
1225                         }
1226
1227                         if (counter == 0)
1228                                 throw new InvalidOperationException ();
1229                         
1230                         return initValue;
1231                 }
1232
1233                 public static int? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1234                 {
1235                         CheckSourceAndSelector (source, selector);
1236
1237                         bool onlyNull = true;
1238                         int? maximum = int.MinValue;
1239                         foreach (TSource item in source) {
1240                                 int? element = selector (item);
1241                                 if (element.HasValue) {
1242                                         onlyNull = false;
1243                                         if (element > maximum)
1244                                                 maximum = element;
1245                                 }
1246                         }
1247                         return (onlyNull ? null : maximum);
1248                 }
1249                 
1250                 public static long? Max<TSource> (this IEnumerable<TSource> source,
1251                         Func<TSource, long?> selector)
1252                 {
1253                         CheckSourceAndSelector (source, selector);
1254
1255                         bool onlyNull = true;
1256                         long? maximum = long.MinValue;
1257                         foreach (TSource item in source) {
1258                                 long? element = selector (item);
1259                                 if (element.HasValue) {
1260                                         onlyNull = false;
1261                                         if (element > maximum)
1262                                                 maximum = element;
1263                                 }
1264                         }
1265                         return (onlyNull ? null : maximum);
1266                 }
1267
1268                 public static double? Max<TSource> (this IEnumerable<TSource> source,
1269                         Func<TSource, double?> selector)
1270                 {
1271                         CheckSourceAndSelector (source, selector);
1272
1273                         bool onlyNull = true;
1274                         double? maximum = double.MinValue;
1275                         foreach (TSource item in source) {
1276                                 double? element = selector (item);
1277                                 if (element.HasValue) {
1278                                         onlyNull = false;
1279                                         if (element > maximum)
1280                                                 maximum = element;
1281                                 }
1282                         }
1283                         return (onlyNull ? null : maximum);
1284                 }
1285
1286
1287                 public static decimal? Max<TSource> (this IEnumerable<TSource> source,
1288                         Func<TSource, decimal?> selector)
1289                 {
1290                         CheckSourceAndSelector (source, selector);
1291
1292                         bool onlyNull = true;
1293                         decimal? maximum = decimal.MinValue;
1294                         foreach (TSource item in source) {
1295                                 decimal? element = selector (item);
1296                                 if (element.HasValue) {
1297                                         onlyNull = false;
1298                                         if (element > maximum)
1299                                                 maximum = element;
1300                                 }
1301                         }
1302                         return (onlyNull ? null : maximum);
1303                 }
1304
1305                 public static TResult Max<TSource, TResult> (this IEnumerable<TSource> source,
1306                                 Func<TSource, TResult> selector)
1307                 {
1308                         CheckSourceAndSelector (source, selector);
1309
1310                         bool notAssigned = true;
1311                         TResult maximum = default (TResult);
1312                         int counter = 0;
1313                         foreach (TSource item in source) {
1314                                 TResult element = selector (item);
1315                                 if (notAssigned) {
1316                                         maximum = element;
1317                                         notAssigned = false;
1318                                 } else {
1319                                         int comparison;
1320                                         if (element is IComparable<TResult>)
1321                                                 comparison = ((IComparable<TResult>) element).CompareTo (maximum);
1322                                         else if (element is System.IComparable)
1323                                                 comparison = ((System.IComparable) element).CompareTo (maximum);
1324                                         else
1325                                                 throw new ArgumentNullException ();
1326
1327                                         if (comparison > 0)
1328                                                 maximum = element;
1329                                 }
1330                                 counter++;
1331                         }
1332
1333                         if (counter == 0)
1334                                 throw new InvalidOperationException ();
1335                         else
1336                                 return maximum;
1337                 }
1338
1339                 #endregion
1340
1341                 #region Min
1342
1343                 public static int Min (this IEnumerable<int> source)
1344                 {
1345                         return Iterate (source, int.MaxValue, (a, b) => a < b);
1346                 }
1347
1348                 public static long Min (this IEnumerable<long> source)
1349                 {
1350                         return Iterate (source, long.MaxValue, (a, b) => a < b);
1351                 }
1352                 
1353                 public static double Min (this IEnumerable<double> source)
1354                 {
1355                         return Iterate (source, double.MaxValue, (a, b) => a < b);
1356                 }
1357
1358                 public static float Min (this IEnumerable<float> source)
1359                 {
1360                         return Iterate (source, float.MaxValue, (a, b) => a < b);
1361                 }
1362
1363                 public static decimal Min (this IEnumerable<decimal> source)
1364                 {
1365                         return Iterate (source, decimal.MaxValue, (a, b) => a < b);
1366                 }
1367
1368                 public static int? Min (this IEnumerable<int?> source)
1369                 {
1370                         return IterateNullable (source, int.MaxValue, (a, b) => a < b);
1371                 }
1372
1373                 public static long? Min (this IEnumerable<long?> source)
1374                 {
1375                         return IterateNullable (source, long.MaxValue, (a, b) => a < b);
1376                 }
1377                 
1378                 public static double? Min (this IEnumerable<double?> source)
1379                 {
1380                         return IterateNullable (source, double.MaxValue, (a, b) => a < b);
1381                 }
1382
1383                 public static float? Min (this IEnumerable<float?> source)
1384                 {
1385                         return IterateNullable (source, float.MaxValue, (a, b) => a < b);
1386                 }
1387
1388                 public static decimal? Min (this IEnumerable<decimal?> source)
1389                 {
1390                         return IterateNullable (source, decimal.MaxValue, (a, b) => a < b);
1391                 }
1392                 
1393                 public static TSource Min<TSource> (this IEnumerable<TSource> source)
1394                 {
1395                         CheckSource (source);
1396
1397                         bool notAssigned = true;
1398                         TSource minimum = default (TSource);
1399                         int counter = 0;
1400                         foreach (TSource element in source) {
1401                                 if (notAssigned) {
1402                                         minimum = element;
1403                                         notAssigned = false;
1404                                 } else {
1405                                         int comparison;
1406                                         if (element is IComparable<TSource>)
1407                                                 comparison = ((IComparable<TSource>) element).CompareTo (minimum);
1408                                         else if (element is System.IComparable)
1409                                                 comparison = ((System.IComparable) element).CompareTo (minimum);
1410                                         else
1411                                                 throw new ArgumentNullException ();
1412
1413                                         if (comparison < 0)
1414                                                 minimum = element;
1415                                 }
1416                                 counter++;
1417                         }
1418
1419                         if (counter == 0)
1420                                 throw new InvalidOperationException ();
1421                         else
1422                                 return minimum;
1423                 }
1424
1425                 public static int Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1426                 {
1427                         return Iterate (source, int.MaxValue, (a, b) => { 
1428                                 var v = selector (a); return v < b ? v : b;
1429                         });
1430                 }
1431                 
1432                 public static long Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1433                 {
1434                         return Iterate (source, long.MaxValue, (a, b) => { 
1435                                 var v = selector (a); return v < b ? v : b;
1436                         });
1437                 }
1438                 
1439                 public static double Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1440                 {
1441                         return Iterate (source, double.MaxValue, (a, b) => { 
1442                                 var v = selector (a); return v < b ? v : b;
1443                         });
1444                 }
1445                 
1446                 public static float Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1447                 {
1448                         return Iterate (source, float.MaxValue, (a, b) => { 
1449                                 var v = selector (a); return v < b ? v : b;
1450                         });
1451                 }
1452                 
1453                 public static decimal Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1454                 {
1455                         return Iterate (source, decimal.MaxValue, (a, b) => { 
1456                                 var v = selector (a); return v < b ? v : b;
1457                         });
1458                 }
1459
1460                 public static int? Min<TSource> (this IEnumerable<TSource> source,
1461                                 Func<TSource, int?> selector)
1462                 {
1463                         CheckSourceAndSelector (source, selector);
1464
1465                         bool onlyNull = true;
1466                         int? minimum = int.MaxValue;
1467                         foreach (TSource item in source) {
1468                                 int? element = selector (item);
1469                                 if (element.HasValue) {
1470                                         onlyNull = false;
1471                                         if (element < minimum)
1472                                                 minimum = element;
1473                                 }
1474                         }
1475                         return (onlyNull ? null : minimum);
1476                 }
1477
1478                 public static long? Min<TSource> (this IEnumerable<TSource> source,
1479                                 Func<TSource, long?> selector)
1480                 {
1481                         CheckSourceAndSelector (source, selector);
1482
1483                         bool onlyNull = true;
1484                         long? minimum = long.MaxValue;
1485                         foreach (TSource item in source) {
1486                                 long? element = selector (item);
1487                                 if (element.HasValue) {
1488                                         onlyNull = false;
1489                                         if (element < minimum)
1490                                                 minimum = element;
1491                                 }
1492                         }
1493                         return (onlyNull ? null : minimum);
1494                 }
1495
1496                 public static double? Min<TSource> (this IEnumerable<TSource> source,
1497                                 Func<TSource, double?> selector)
1498                 {
1499                         CheckSourceAndSelector (source, selector);
1500
1501                         bool onlyNull = true;
1502                         double? minimum = double.MaxValue;
1503                         foreach (TSource item in source) {
1504                                 double? element = selector (item);
1505                                 if (element.HasValue) {
1506                                         onlyNull = false;
1507                                         if (element < minimum)
1508                                                 minimum = element;
1509                                 }
1510                         }
1511                         return (onlyNull ? null : minimum);
1512                 }
1513
1514                 public static decimal? Min<TSource> (this IEnumerable<TSource> source,
1515                                 Func<TSource, decimal?> selector)
1516                 {
1517                         CheckSourceAndSelector (source, selector);
1518
1519                         bool onlyNull = true;
1520                         decimal? minimum = decimal.MaxValue;
1521                         foreach (TSource item in source) {
1522                                 decimal? element = selector (item);
1523                                 if (element.HasValue) {
1524                                         onlyNull = false;
1525                                         if (element < minimum)
1526                                                 minimum = element;
1527                                 }
1528                         }
1529                         return (onlyNull ? null : minimum);
1530                 }
1531
1532
1533                 public static TResult Min<TSource, TResult> (this IEnumerable<TSource> source,
1534                                 Func<TSource, TResult> selector)
1535                 {
1536                         CheckSourceAndSelector (source, selector);
1537
1538                         bool notAssigned = true;
1539                         TResult minimum = default (TResult);
1540                         int counter = 0;
1541                         foreach (TSource item in source) {
1542                                 TResult element = selector (item);
1543                                 if (notAssigned) {
1544                                         minimum = element;
1545                                         notAssigned = false;
1546                                 } else {
1547                                         int comparison;
1548                                         if (element is IComparable<TResult>)
1549                                                 comparison = ((IComparable<TResult>) element).CompareTo (minimum);
1550                                         else if (element is System.IComparable)
1551                                                 comparison = ((System.IComparable) element).CompareTo (minimum);
1552                                         else
1553                                                 throw new ArgumentNullException ();
1554
1555                                         if (comparison < 0)
1556                                                 minimum = element;
1557                                 }
1558                                 counter++;
1559                         }
1560
1561                         if (counter == 0)
1562                                 throw new InvalidOperationException ();
1563                         else
1564                                 return minimum;
1565                 }
1566
1567                 #endregion
1568
1569                 #region OfType
1570
1571                 public static IEnumerable<TResult> OfType<TResult> (this IEnumerable source)
1572                 {
1573                         CheckSource (source);
1574
1575                         foreach (object element in source)
1576                                 if (element is TResult)
1577                                         yield return (TResult) element;
1578                 }
1579
1580                 #endregion
1581
1582                 #region OrderBy
1583
1584                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
1585                                 Func<TSource, TKey> keySelector)
1586                 {
1587                         return OrderBy<TSource, TKey> (source, keySelector, null);
1588                 }
1589
1590
1591                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
1592                                 Func<TSource, TKey> keySelector,
1593                                 IComparer<TKey> comparer)
1594                 {
1595                         CheckSourceAndKeySelector (source, keySelector);
1596
1597                         return new InternalOrderedSequence<TSource, TKey> (
1598                                         source, keySelector, comparer, false);
1599                 }
1600
1601                 #endregion
1602
1603                 #region OrderByDescending
1604
1605                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
1606                                 Func<TSource, TKey> keySelector)
1607                 {
1608                         return OrderByDescending<TSource, TKey> (source, keySelector, null);
1609                 }
1610
1611
1612                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
1613                                 Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
1614                 {
1615                         CheckSourceAndKeySelector (source, keySelector);
1616
1617                         return new InternalOrderedSequence<TSource, TKey> (
1618                                         source, keySelector, comparer, true);
1619                 }
1620
1621                 #endregion
1622
1623                 #region Range
1624
1625                 public static IEnumerable<int> Range (int start, int count)
1626                 {
1627                         int upto = (start + count - 1);
1628
1629                         if (count < 0 || upto > int.MaxValue)
1630                                 throw new ArgumentOutOfRangeException ();
1631
1632                         for (int i = start; i <= upto; i++)
1633                                 yield return i;
1634                 }
1635
1636                 #endregion
1637
1638                 #region Repeat
1639
1640                 public static IEnumerable<TResult> Repeat<TResult> (TResult element, int count)
1641                 {
1642                         if (count < 0)
1643                                 throw new ArgumentOutOfRangeException ();
1644
1645                         for (int i = 0; i < count; i++)
1646                                 yield return element;
1647                 }
1648
1649                 #endregion
1650
1651
1652                 #region Reverse
1653
1654                 public static IEnumerable<TSource> Reverse<TSource> (this IEnumerable<TSource> source)
1655                 {
1656                         CheckSource (source);
1657
1658                         List<TSource> list = new List<TSource> (source);
1659                         list.Reverse ();
1660                         return list;
1661                 }
1662
1663                 #endregion
1664
1665                 #region Select
1666
1667                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source,
1668                                 Func<TSource, TResult> selector)
1669                 {
1670                         CheckSourceAndSelector (source, selector);
1671
1672                         foreach (TSource element in source)
1673                                 yield return selector (element);
1674                 }
1675
1676                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source,
1677                                 Func<TSource, int, TResult> selector)
1678                 {
1679                         CheckSourceAndSelector (source, selector);
1680
1681                         int counter = 0;
1682                         foreach (TSource element in source) {
1683                                 yield return selector (element, counter);
1684                                 counter++;
1685                         }
1686                 }
1687
1688                 #endregion
1689
1690                 #region SelectMany
1691
1692                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source,
1693                                 Func<TSource, IEnumerable<TResult>> selector)
1694                 {
1695                         CheckSourceAndSelector (source, selector);
1696
1697                         foreach (TSource element in source)
1698                                 foreach (TResult item in selector (element))
1699                                         yield return item;
1700                 }
1701
1702
1703                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source,
1704                                 Func<TSource, int, IEnumerable<TResult>> selector)
1705                 {
1706                         CheckSourceAndSelector (source, selector);
1707
1708                         int counter = 0;
1709                         foreach (TSource element in source) {
1710                                 foreach (TResult item in selector (element, counter++))
1711                                         yield return item;
1712                                 counter++;
1713                         }
1714                 }
1715
1716                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
1717                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1718                 {
1719                         CheckSourceAndCollectionSelectors (source, collectionSelector, selector);
1720
1721                         foreach (TSource element in source)
1722                                 foreach (TCollection collection in collectionSelector (element))
1723                                         yield return selector (element, collection);
1724                 }
1725
1726                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
1727                 Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1728                 {
1729                         CheckSourceAndCollectionSelectors (source, collectionSelector, selector);
1730
1731                         int counter = 0;
1732                         foreach (TSource element in source)
1733                                 foreach (TCollection collection in collectionSelector (element, counter++))
1734                                         yield return selector (element, collection);
1735                 }
1736
1737                 #endregion
1738
1739                 #region Single
1740
1741                 public static TSource Single<TSource> (this IEnumerable<TSource> source)
1742                 {
1743                         CheckSource (source);
1744
1745                         bool otherElement = false;
1746                         TSource singleElement = default (TSource);
1747                         foreach (TSource element in source) {
1748                                 if (otherElement) throw new InvalidOperationException ();
1749                                 if (!otherElement) otherElement = true;
1750                                 singleElement = element;
1751                         }
1752
1753                         if (otherElement)
1754                                 return singleElement;
1755                         else
1756                                 throw new InvalidOperationException ();
1757                 }
1758
1759
1760                 public static TSource Single<TSource> (this IEnumerable<TSource> source,
1761                                 Func<TSource, bool> predicate)
1762                 {
1763                         CheckSourceAndPredicate (source, predicate);
1764
1765                         bool otherElement = false;
1766                         TSource singleElement = default (TSource);
1767                         foreach (TSource element in source) {
1768                                 if (predicate (element)) {
1769                                         if (otherElement) throw new InvalidOperationException ();
1770                                         if (!otherElement) otherElement = true;
1771                                         singleElement = element;
1772                                 }
1773                         }
1774
1775                         if (otherElement)
1776                                 return singleElement;
1777                         else
1778                                 throw new InvalidOperationException ();
1779                 }
1780
1781                 #endregion
1782
1783                 #region SingleOrDefault
1784
1785                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source)
1786                 {
1787                         CheckSource (source);
1788
1789                         bool otherElement = false;
1790                         TSource singleElement = default (TSource);
1791                         foreach (TSource element in source) {
1792                                 if (otherElement) throw new InvalidOperationException ();
1793                                 if (!otherElement) otherElement = true;
1794                                 singleElement = element;
1795                         }
1796
1797                         return singleElement;
1798                 }
1799
1800
1801                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source,
1802                                 Func<TSource, bool> predicate)
1803                 {
1804                         CheckSourceAndPredicate (source, predicate);
1805
1806                         bool otherElement = false;
1807                         TSource singleElement = default (TSource);
1808                         foreach (TSource element in source) {
1809                                 if (predicate (element)) {
1810                                         if (otherElement) throw new InvalidOperationException ();
1811                                         if (!otherElement) otherElement = true;
1812                                         singleElement = element;
1813                                 }
1814                         }
1815
1816                         return singleElement;
1817                 }
1818
1819                 #endregion
1820
1821                 #region Skip
1822                 public static IEnumerable<TSource> Skip<TSource> (this IEnumerable<TSource> source, int count)
1823                 {
1824                         CheckSource (source);
1825
1826                         int i = 0;
1827                         foreach (var element in source) {
1828                                 if (i++ < count)
1829                                         continue;
1830
1831                                 yield return element;
1832                         }
1833                 }
1834                 #endregion
1835
1836                 #region SkipWhile
1837
1838
1839                 public static IEnumerable<TSource> SkipWhile<TSource> (
1840                                 this IEnumerable<TSource> source,
1841                                 Func<TSource, bool> predicate)
1842                 {
1843                         CheckSourceAndPredicate (source, predicate);
1844
1845                         bool yield = false;
1846
1847                         foreach (TSource element in source) {
1848                                 if (yield)
1849                                         yield return element;
1850                                 else
1851                                         if (!predicate (element)) {
1852                                                 yield return element;
1853                                                 yield = true;
1854                                         }
1855                         }
1856                 }
1857
1858                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source,
1859                                 Func<TSource, int, bool> predicate)
1860                 {
1861                         CheckSourceAndPredicate (source, predicate);
1862
1863                         int counter = 0;
1864                         bool yield = false;
1865
1866                         foreach (TSource element in source) {
1867                                 if (yield)
1868                                         yield return element;
1869                                 else
1870                                         if (!predicate (element, counter)) {
1871                                                 yield return element;
1872                                                 yield = true;
1873                                         }
1874                                 counter++;
1875                         }
1876                 }
1877
1878                 #endregion
1879
1880                 #region Sum
1881
1882                 public static int Sum (this IEnumerable<int> source)
1883                 {
1884                         return Sum<int, int> (source, (a, b) => a + b);
1885                 }
1886                 
1887                 public static int? Sum (this IEnumerable<int?> source)
1888                 {
1889                         return SumNullable<int?, int?> (source, (a, b) => a.HasValue ? a + b : a);
1890                 }
1891                 
1892                 public static int Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1893                 {
1894                         return Sum<TSource, int> (source, (a, b) => a + selector (b));
1895                 }
1896                 
1897                 public static int? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1898                 {
1899                         return SumNullable<TSource, int?> (source, (a, b) => { 
1900                                 var value = selector (b);
1901                                 return value.HasValue ? a + value.Value : a;
1902                         });
1903                 }
1904                 
1905                 public static long Sum (this IEnumerable<long> source)
1906                 {
1907                         return Sum<long, long> (source, (a, b) => a + b);
1908                 }
1909                 
1910                 public static long? Sum (this IEnumerable<long?> source)
1911                 {
1912                         return SumNullable<long?, long?> (source, (a, b) => a.HasValue ? a + b : a);
1913                 }               
1914                 
1915                 public static long Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1916                 {
1917                         return Sum<TSource, long> (source, (a, b) => a + selector (b));
1918                 }
1919                 
1920                 public static long? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1921                 {
1922                         return SumNullable<TSource, long?> (source, (a, b) => { 
1923                                 var value = selector (b);
1924                                 return value.HasValue ? a + value.Value : a;
1925                         });
1926                 }       
1927                 
1928                 public static double Sum (this IEnumerable<double> source)
1929                 {
1930                         return Sum<double, double> (source, (a, b) => a + b);
1931                 }
1932                 
1933                 public static double? Sum (this IEnumerable<double?> source)
1934                 {
1935                         return SumNullable<double?, double?> (source, (a, b) => a.HasValue ? a + b : a);
1936                 }
1937                 
1938                 public static double Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1939                 {
1940                         return Sum<TSource, double> (source, (a, b) => a + selector (b));
1941                 }
1942                 
1943                 public static double? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1944                 {
1945                         return SumNullable<TSource, double?> (source, (a, b) => { 
1946                                 var value = selector (b);
1947                                 return value.HasValue ? a + value.Value : a;
1948                         });
1949                 }       
1950                 
1951                 public static float Sum (this IEnumerable<float> source)
1952                 {
1953                         return Sum<float, float> (source, (a, b) => a + b);
1954                 }
1955                 
1956                 public static float? Sum (this IEnumerable<float?> source)
1957                 {
1958                         return SumNullable<float?, float?> (source, (a, b) => a.HasValue ? a + b : a);
1959                 }               
1960                 
1961                 public static float Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1962                 {
1963                         return Sum<TSource, float> (source, (a, b) => a + selector (b));
1964                 }
1965                 
1966                 public static float? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1967                 {
1968                         return SumNullable<TSource, float?> (source, (a, b) => { 
1969                                 var value = selector (b);
1970                                 return value.HasValue ? a + value.Value : a;
1971                         });
1972                 }               
1973                 
1974                 public static decimal Sum (this IEnumerable<decimal> source)
1975                 {
1976                         return Sum<decimal, decimal> (source, (a, b) => a + b);
1977                 }
1978                 
1979                 public static decimal? Sum (this IEnumerable<decimal?> source)
1980                 {
1981                         return SumNullable<decimal?, decimal?> (source, (a, b) => a.HasValue ? a + b : a);
1982                 }               
1983                 
1984                 public static decimal Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1985                 {
1986                         return Sum<TSource, decimal> (source, (a, b) => a + selector (b));
1987                 }
1988                 
1989                 public static decimal? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1990                 {
1991                         return SumNullable<TSource, decimal?> (source, (a, b) => { 
1992                                 var value = selector (b);
1993                                 return value.HasValue ? a + value.Value : a;
1994                         });
1995                 }               
1996                 
1997                 static TR Sum<TA, TR> (this IEnumerable<TA> source, Func<TR, TA, TR> func)
1998                 {
1999                         CheckSource (source);
2000
2001                         TR total = default (TR);
2002                         int counter = 0;
2003                         foreach (var element in source) {
2004                                 total = func (total, element);
2005                                 ++counter;
2006                         }
2007
2008                         if (counter == 0)
2009                                 throw new InvalidOperationException ();
2010                                 
2011                         return total;
2012                 }
2013                 
2014                 static TR SumNullable<TA, TR> (this IEnumerable<TA> source, Func<TR, TA, TR> func)
2015                 {
2016                         CheckSource (source);
2017
2018                         TR total = default (TR);
2019                         foreach (var element in source) {
2020                                 total = func (total, element);
2021                         }
2022
2023                         return total;
2024                 }
2025
2026                 #endregion
2027
2028                 #region Take
2029
2030                 public static IEnumerable<TSource> Take<TSource> (this IEnumerable<TSource> source, int count)
2031                 {
2032                         CheckSource (source);
2033
2034                         if (count <= 0)
2035                                 yield break;
2036
2037                         int counter = 0;
2038                         foreach (TSource element in source) {
2039                                 if (counter++ == count)
2040                                         yield break;
2041
2042                                 yield return element;
2043                         }
2044                 }
2045
2046                 #endregion
2047
2048                 #region TakeWhile
2049
2050                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2051                 {
2052                         CheckSourceAndPredicate (source, predicate);
2053
2054                         foreach (TSource element in source) {
2055                                 if (!predicate (element))
2056                                         yield break;
2057
2058                                 yield return element;
2059                         }
2060                 }
2061
2062                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2063                 {
2064                         CheckSourceAndPredicate (source, predicate);
2065
2066                         int counter = 0;
2067                         foreach (var element in source) {
2068                                 if (!predicate (element, counter))
2069                                         yield break;
2070
2071                                 yield return element;
2072                                 counter++;
2073                         }
2074                 }
2075
2076                 #endregion
2077
2078                 #region ThenBy
2079
2080                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2081                 {
2082                         return ThenBy<TSource, TKey> (source, keySelector, null);
2083                 }
2084
2085
2086                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2087                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2088                 {
2089                         CheckSourceAndKeySelector (source, keySelector);
2090
2091                         return source.CreateOrderedEnumerable (keySelector, comparer, false);
2092                 }
2093
2094                 #endregion
2095
2096                 #region ThenByDescending
2097
2098                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2099                         Func<TSource, TKey> keySelector)
2100                 {
2101                         return ThenByDescending<TSource, TKey> (source, keySelector, null);
2102                 }
2103
2104
2105                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2106                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2107                 {
2108                         CheckSourceAndKeySelector (source, keySelector);
2109
2110                         return source.CreateOrderedEnumerable (keySelector, comparer, true);
2111                 }
2112
2113                 #endregion
2114
2115                 #region ToArray
2116                 public static TSource [] ToArray<TSource> (this IEnumerable<TSource> source)
2117                 {
2118                         CheckSource (source);
2119
2120                         List<TSource> list = new List<TSource> (source);
2121                         return list.ToArray ();
2122                 }
2123
2124                 #endregion
2125
2126                 #region ToDictionary
2127                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2128                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2129                 {
2130                         return ToDictionary<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2131                 }
2132
2133                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2134                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2135                 {
2136                         CheckSourceAndKeyElementSelectors (source, keySelector, elementSelector);
2137
2138                         var dict = new Dictionary<TKey, TElement> (comparer);
2139                         foreach (var e in source)
2140                                 dict.Add (keySelector (e), elementSelector (e));
2141
2142                         return dict;
2143                 }
2144                 
2145                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2146                                 Func<TSource, TKey> keySelector)
2147                 {
2148                         return ToDictionary (source, keySelector, null);
2149                 }
2150
2151                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2152                                 Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2153                 {
2154                         throw new NotImplementedException ();
2155                         // FIXME: compiler issue
2156                         //return ToDictionary (source, keySelector, (a) => a, comparer);
2157                 }
2158                 
2159                 #endregion
2160
2161                 #region ToList
2162                 public static List<TSource> ToList<TSource> (this IEnumerable<TSource> source)
2163                 {
2164                         CheckSource (source);
2165
2166                         return new List<TSource> (source);
2167                 }
2168                 #endregion
2169
2170                 #region ToLookup
2171
2172                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2173                 {
2174                         return ToLookup<TSource, TKey> (source, keySelector, null);
2175                 }
2176
2177                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source,
2178                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2179                 {
2180                         CheckSourceAndKeySelector (source, keySelector);
2181
2182                         var dictionary = new Dictionary<TKey, List<TSource>> (comparer ?? EqualityComparer<TKey>.Default);
2183                         foreach (TSource element in source) {
2184                                 TKey key = keySelector (element);
2185                                 if (key == null)
2186                                         throw new ArgumentNullException ();
2187                                 if (!dictionary.ContainsKey (key))
2188                                         dictionary.Add (key, new List<TSource> ());
2189                                 dictionary [key].Add (element);
2190                         }
2191                         return new Lookup<TKey, TSource> (dictionary);
2192                 }
2193
2194                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2195                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2196                 {
2197                         return ToLookup<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2198                 }
2199
2200                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2201                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2202                 {
2203                         CheckSourceAndKeyElementSelectors (source, keySelector, elementSelector);
2204
2205                         Dictionary<TKey, List<TElement>> dictionary = new Dictionary<TKey, List<TElement>> (comparer ?? EqualityComparer<TKey>.Default);
2206                         foreach (TSource element in source) {
2207                                 TKey key = keySelector (element);
2208                                 if (key == null)
2209                                         throw new ArgumentNullException ();
2210                                 if (!dictionary.ContainsKey (key))
2211                                         dictionary.Add (key, new List<TElement> ());
2212                                 dictionary [key].Add (elementSelector (element));
2213                         }
2214                         return new Lookup<TKey, TElement> (dictionary);
2215                 }
2216
2217                 #endregion
2218
2219                 #region SequenceEqual
2220
2221                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2222                 {
2223                         return first.SequenceEqual (second, null);
2224                 }
2225
2226                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2227                 {
2228                         CheckFirstAndSecond (first, second);
2229
2230                         if (comparer == null)
2231                                 comparer = EqualityComparer<TSource>.Default;
2232
2233                         var first_enumerator = first.GetEnumerator ();
2234                         var second_enumerator = second.GetEnumerator ();
2235
2236                         while (first_enumerator.MoveNext ()) {
2237                                 if (!second_enumerator.MoveNext ())
2238                                         return false;
2239
2240                                 if (!comparer.Equals (first_enumerator.Current, second_enumerator.Current))
2241                                         return false;
2242                         }
2243
2244                         return !second_enumerator.MoveNext ();
2245                 }
2246
2247                 #endregion
2248
2249                 #region Union
2250
2251                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2252                 {
2253                         CheckFirstAndSecond (first, second);
2254
2255                         return first.Union (second, null);
2256                 }
2257
2258                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2259                 {
2260                         CheckFirstAndSecond (first, second);
2261
2262                         if (comparer == null)
2263                                 comparer = EqualityComparer<TSource>.Default;
2264
2265                         var items = new List<TSource> (); // TODO: use a HashSet here
2266                         foreach (var element in first) {
2267                                 if (! items.Contains (element, comparer)) {
2268                                         items.Add (element);
2269                                         yield return element;
2270                                 }
2271                         }
2272
2273                         foreach (var element in second) {
2274                                 if (! items.Contains (element, comparer)) {
2275                                         items.Add (element);
2276                                         yield return element;
2277                                 }
2278                         }
2279                 }
2280
2281                 #endregion
2282
2283                 #region Where
2284
2285                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source,
2286                                 Func<TSource, bool> predicate)
2287                 {
2288                         CheckSourceAndPredicate (source, predicate);
2289
2290                         foreach (TSource element in source)
2291                                 if (predicate (element))
2292                                         yield return element;
2293                 }
2294
2295
2296                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source,
2297                                 Func<TSource, int, bool> predicate)
2298                 {
2299                         CheckSourceAndPredicate (source, predicate);
2300
2301                         int counter = 0;
2302                         foreach (TSource element in source) {
2303                                 if (predicate (element, counter))
2304                                         yield return element;
2305                                 counter++;
2306                         }
2307                 }
2308
2309                 #endregion
2310
2311                 // These methods are not included in the
2312                 // .NET Standard Query Operators Specification,
2313                 // but they provide additional useful commands
2314
2315                 #region Checks
2316
2317                 static void CheckSource (object source)
2318                 {
2319                         if (source == null)
2320                                 throw new ArgumentNullException ("source");
2321                 }
2322
2323                 static void CheckSourceAndFunc (object source, object func)
2324                 {
2325                         if (source == null)
2326                                 throw new ArgumentNullException ("source");
2327                         if (func == null)
2328                                 throw new ArgumentNullException ("func");
2329                 }
2330
2331                 static void CheckSourceAndSelector (object source, object selector)
2332                 {
2333                         if (source == null)
2334                                 throw new ArgumentNullException ("source");
2335                         if (selector == null)
2336                                 throw new ArgumentNullException ("selector");
2337                 }
2338
2339                 static void CheckSourceAndPredicate (object source, object predicate)
2340                 {
2341                         if (source == null)
2342                                 throw new ArgumentNullException ("source");
2343                         if (predicate == null)
2344                                 throw new ArgumentNullException ("predicate");
2345                 }
2346
2347                 static void CheckFirstAndSecond (object first, object second)
2348                 {
2349                         if (first == null)
2350                                 throw new ArgumentNullException ("first");
2351                         if (second == null)
2352                                 throw new ArgumentNullException ("second");
2353                 }
2354
2355                 static void CheckSourceAndKeySelector (object source, object keySelector)
2356                 {
2357                         if (source == null)
2358                                 throw new ArgumentNullException ("source");
2359                         if (keySelector == null)
2360                                 throw new ArgumentNullException ("keySelector");
2361                 }
2362
2363                 static void CheckSourceAndKeyElementSelectors (object source, object keySelector, object elementSelector)
2364                 {
2365                         if (source == null)
2366                                 throw new ArgumentNullException ("source");
2367                         if (keySelector == null)
2368                                 throw new ArgumentNullException ("keySelector");
2369                         if (elementSelector == null)
2370                                 throw new ArgumentNullException ("elementSelector");
2371                 }
2372
2373                 static void CheckSourceAndCollectionSelectors (object source, object collectionSelector, object selector)
2374                 {
2375                         if (source == null)
2376                                 throw new ArgumentNullException ("source");
2377                         if (collectionSelector == null)
2378                                 throw new ArgumentNullException ("collectionSelector");
2379                         if (selector == null)
2380                                 throw new ArgumentNullException ("selector");
2381                 }
2382
2383                 static void CheckJoinSelectors (object outer, object inner, object outerKeySelector, object innerKeySelector, object resultSelector)
2384                 {
2385                         if (outer == null)
2386                                 throw new ArgumentNullException ("outer");
2387                         if (inner == null)
2388                                 throw new ArgumentNullException ("inner");
2389                         if (outerKeySelector == null)
2390                                 throw new ArgumentNullException ("outerKeySelector");
2391                         if (innerKeySelector == null)
2392                                 throw new ArgumentNullException ("innerKeySelector");
2393                         if (resultSelector == null)
2394                                 throw new ArgumentNullException ("resultSelector");
2395                 }
2396
2397                 #endregion
2398
2399                 #region ToReadOnlyCollection
2400                 internal static ReadOnlyCollection<TSource> ToReadOnlyCollection<TSource> (IEnumerable<TSource> source)
2401                 {
2402                         if (source == null)
2403                                 return new ReadOnlyCollection<TSource> (new List<TSource> ());
2404
2405                         if (typeof (ReadOnlyCollection<TSource>).IsInstanceOfType (source))
2406                                 return source as ReadOnlyCollection<TSource>;
2407
2408                         return new ReadOnlyCollection<TSource> (ToArray<TSource> (source));
2409                 }
2410                 #endregion
2411         }
2412 }