ef51cf05e03feaf2b052d400aac05c9973877ae1
[mono.git] / mcs / class / System.Core / System.Linq / Enumerable.cs
1 //
2 // Enumerable.cs
3 //
4 // Authors:
5 //  Marek Safar (marek.safar@gmail.com)
6 //  Antonello Provenzano  <antonello@deveel.com>
7 //  Alejandro Serrano "Serras" (trupill@yahoo.es)
8 //  Jb Evain (jbevain@novell.com)
9 //
10 // Copyright (C) 2007 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 // precious: http://www.hookedonlinq.com
33
34 using System;
35 using System.Collections;
36 using System.Collections.Generic;
37 using System.Collections.ObjectModel;
38
39 namespace System.Linq
40 {
41         public static class Enumerable
42         {
43                 #region Aggregate
44
45                 public static TSource Aggregate<TSource> (this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func)
46                 {
47                         Check.SourceAndFunc (source, func);
48
49                         // custom foreach so that we can efficiently throw an exception 
50                         // if zero elements and treat the first element differently
51                         using (var enumerator = source.GetEnumerator ()) {
52                                 if (!enumerator.MoveNext ())
53                                         throw new InvalidOperationException ("No elements in source list");
54
55                                 TSource folded = enumerator.Current;
56                                 while (enumerator.MoveNext ())
57                                         folded = func (folded, enumerator.Current);
58                                 return folded;
59                         }
60                 }
61
62                 public static TAccumulate Aggregate<TSource, TAccumulate> (this IEnumerable<TSource> source,
63                         TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func)
64                 {
65                         Check.SourceAndFunc (source, func);
66
67                         TAccumulate folded = seed;
68                         foreach (TSource element in source)
69                                 folded = func (folded, element);
70
71                         return folded;
72                 }
73
74                 public static TResult Aggregate<TSource, TAccumulate, TResult> (this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func, Func<TAccumulate, TResult> resultSelector)
75                 {
76                         Check.SourceAndFunc (source, func);
77                         if (resultSelector == null)
78                                 throw new ArgumentNullException ("resultSelector");
79
80                         TAccumulate result = seed;
81                         foreach (TSource e in source)
82                                 result = func (result, e);
83
84                         return resultSelector (result);
85                 }
86
87                 #endregion
88
89                 #region All
90
91                 public static bool All<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
92                 {
93                         Check.SourceAndPredicate (source, predicate);
94
95                         foreach (TSource element in source)
96                                 if (!predicate (element))
97                                         return false;
98
99                         return true;
100                 }
101
102                 #endregion
103
104                 #region Any
105
106                 public static bool Any<TSource> (this IEnumerable<TSource> source)
107                 {
108                         Check.Source (source);
109
110                         using (var enumerator = source.GetEnumerator ())
111                                 return enumerator.MoveNext ();
112                 }
113
114                 public static bool Any<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
115                 {
116                         Check.SourceAndPredicate (source, predicate);
117
118                         foreach (TSource element in source)
119                                 if (predicate (element))
120                                         return true;
121
122                         return false;
123                 }
124
125                 #endregion
126
127                 #region AsEnumerable
128
129                 public static IEnumerable<TSource> AsEnumerable<TSource> (this IEnumerable<TSource> source)
130                 {
131                         return source;
132                 }
133
134                 #endregion
135
136                 #region Average
137                 
138                 public static double Average (this IEnumerable<int> source)
139                 {
140                         return Average (source, (a, b) => a + b, (a, b) => a / b);
141                 }
142                 
143                 public static double Average (this IEnumerable<long> source)
144                 {
145                         return Average (source, (a, b) => a + b, (a, b) => a / b);              
146                 }
147                 
148                 public static double Average (this IEnumerable<double> source)
149                 {
150                         return Average (source, (a, b) => a + b, (a, b) => a / b);                              
151                 }
152
153                 public static float Average (this IEnumerable<float> source)
154                 {
155                         return Average (source, (a, b) => a + b, (a, b) => a / b);                              
156                 }
157                 
158                 public static decimal Average (this IEnumerable<decimal> source)
159                 {
160                         return Average (source, (a, b) => a + b, (a, b) => a / b);              
161                 }
162
163                 static TR Average<TA, TR> (this IEnumerable<TA> source, Func<TA, TA, TA> func, Func<TA, int, TR> result)
164                 {
165                         Check.Source (source);
166
167                         TA total = default (TA);
168                         int counter = 0;
169                         foreach (var element in source) {
170                                 total = func (total, element);
171                                 ++counter;
172                         }
173
174                         if (counter == 0)
175                                 throw new InvalidOperationException ();
176                                 
177                         return result (total, counter);
178                 }
179
180                 public static double? Average (this IEnumerable<int?> source)
181                 {
182                         Check.Source (source);
183
184                         bool onlyNull = true;
185                         long sum = 0;
186                         long counter = 0;
187                         foreach (int? element in source) {
188                                 if (element.HasValue) {
189                                         onlyNull = false;
190                                         sum += element.Value;
191                                         counter++;
192                                 }
193                         }
194                         return (onlyNull ? null : (double?) sum / (double?) counter);
195                 }
196
197                 public static double? Average (this IEnumerable<long?> source)
198                 {
199                         Check.Source (source);
200
201                         bool onlyNull = true;
202                         long sum = 0;
203                         long counter = 0;
204                         foreach (long? element in source) {
205                                 if (element.HasValue) {
206                                         onlyNull = false;
207                                         sum += element.Value;
208                                         counter++;
209                                 }
210                         }
211                         return (onlyNull ? null : (double?) sum / (double?) counter);
212                 }
213
214                 public static double? Average (this IEnumerable<double?> source)
215                 {
216                         Check.Source (source);
217
218                         bool onlyNull = true;
219                         double sum = 0;
220                         double counter = 0;
221                         foreach (double? element in source) {
222                                 if (element.HasValue) {
223                                         onlyNull = false;
224                                         sum += element.Value;
225                                         counter++;
226                                 }
227                         }
228                         return (onlyNull ? null : (double?) (sum / counter));
229                 }
230
231                 public static decimal? Average (this IEnumerable<decimal?> source)
232                 {
233                         Check.Source (source);
234
235                         bool onlyNull = true;
236                         decimal sum = 0;
237                         decimal counter = 0;
238                         foreach (decimal? element in source) {
239                                 if (element.HasValue) {
240                                         onlyNull = false;
241                                         sum += element.Value;
242                                         counter++;
243                                 }
244                         }
245                         return (onlyNull ? null : (decimal?) (sum / counter));
246                 }
247                 
248                 public static float? Average (this IEnumerable<float?> source)
249                 {
250                         Check.Source (source);
251
252                         float sum = 0;
253                         float counter = 0;
254                         foreach (float? element in source) {
255                                 if (element.HasValue) {
256                                         sum += element.Value;
257                                         ++counter;
258                                 }
259                         }
260
261                         if (counter == 0)
262                                 return null;
263                         
264                         return sum / counter;
265                 }               
266                 
267                 public static double Average<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
268                 {
269                         Check.SourceAndSelector (source, selector);
270
271                         long sum = 0;
272                         long counter = 0;
273                         foreach (TSource item in source) {
274                                 sum += selector (item);
275                                 counter++;
276                         }
277
278                         if (counter == 0)
279                                 throw new InvalidOperationException ();
280                         else
281                                 return (double) sum / (double) counter;
282                 }
283
284                 public static double? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
285                 {
286                         Check.SourceAndSelector (source, selector);
287
288                         bool onlyNull = true;
289                         long sum = 0;
290                         long counter = 0;
291                         foreach (TSource item in source) {
292                                 int? element = selector (item);
293                                 if (element.HasValue) {
294                                         onlyNull = false;
295                                         sum += element.Value;
296                                         counter++;
297                                 }
298                         }
299                         return (onlyNull ? null : (double?) sum / (double?) counter);
300                 }
301
302                 public static double Average<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
303                 {
304                         Check.SourceAndSelector (source, selector);
305
306                         long sum = 0;
307                         long counter = 0;
308                         foreach (TSource item in source) {
309                                 sum += selector (item);
310                                 counter++;
311                         }
312
313                         if (counter == 0)
314                                 throw new InvalidOperationException ();
315                         else
316                                 return (double) sum / (double) counter;
317                 }
318
319                 public static double? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
320                 {
321                         Check.SourceAndSelector (source, selector);
322
323                         bool onlyNull = true;
324                         long sum = 0;
325                         long counter = 0;
326                         foreach (TSource item in source) {
327                                 long? element = selector (item);
328                                 if (element.HasValue) {
329                                         onlyNull = false;
330                                         sum += element.Value;
331                                         counter++;
332                                 }
333                         }
334                         return (onlyNull ? null : (double?) sum / (double?) counter);
335                 }
336
337                 public static double Average<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
338                 {
339                         Check.SourceAndSelector (source, selector);
340
341                         double sum = 0;
342                         double counter = 0;
343                         foreach (TSource item in source) {
344                                 sum += selector (item);
345                                 counter++;
346                         }
347
348                         if (counter == 0)
349                                 throw new InvalidOperationException ();
350                         else
351                                 return sum / counter;
352                 }
353
354                 public static double? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
355                 {
356                         Check.SourceAndSelector (source, selector);
357
358                         bool onlyNull = true;
359                         double sum = 0;
360                         double counter = 0;
361                         foreach (TSource item in source) {
362                                 double? element = selector (item);
363                                 if (element.HasValue) {
364                                         onlyNull = false;
365                                         sum += element.Value;
366                                         counter++;
367                                 }
368                         }
369                         return (onlyNull ? null : (double?) (sum / counter));
370                 }
371
372                 public static float Average<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
373                 {
374                         Check.SourceAndSelector (source, selector);
375
376                         float sum = 0;
377                         float counter = 0;
378                         foreach (TSource item in source) {
379                                 sum += selector (item);
380                                 ++counter;
381                         }
382
383                         if (counter == 0)
384                                 throw new InvalidOperationException ();
385                         
386                         return sum / counter;
387                 }
388                 
389                 public static float? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
390                 {
391                         Check.SourceAndSelector (source, selector);
392
393                         float sum = 0;
394                         float counter = 0;
395                         foreach (TSource item in source) {
396                                 float? value = selector (item);
397                                 if (value.HasValue) {
398                                         sum  += value.Value;
399                                         ++counter;
400                                 }
401                         }
402
403                         if (counter == 0)
404                                 throw new InvalidOperationException ();
405                         
406                         return sum / counter;
407                 }               
408
409                 public static decimal Average<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
410                 {
411                         Check.SourceAndSelector (source, selector);
412
413                         decimal sum = 0;
414                         decimal counter = 0;
415                         foreach (TSource item in source) {
416                                 sum += selector (item);
417                                 counter++;
418                         }
419
420                         if (counter == 0)
421                                 throw new InvalidOperationException ();
422                         else
423                                 return sum / counter;
424                 }
425
426                 public static decimal? Average<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
427                 {
428                         Check.SourceAndSelector (source, selector);
429
430                         bool onlyNull = true;
431                         decimal sum = 0;
432                         decimal counter = 0;
433                         foreach (TSource item in source) {
434                                 decimal? element = selector (item);
435                                 if (element.HasValue) {
436                                         onlyNull = false;
437                                         sum += element.Value;
438                                         counter++;
439                                 }
440                         }
441                         return (onlyNull ? null : (decimal?) (sum / counter));
442                 }
443                 #endregion
444
445                 #region Cast
446
447                 public static IEnumerable<TResult> Cast<TResult> (this IEnumerable source)
448                 {
449                         Check.Source (source);
450
451                         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                         Check.FirstAndSecond (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                         Check.Source (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                         Check.Source (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                         Check.SourceAndSelector (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                         Check.Source (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                         Check.Source (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                         Check.Source (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                         Check.Source (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                         Check.FirstAndSecond (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                         Check.Source (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                         Check.SourceAndPredicate (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                         Check.Source (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                         Check.SourceAndPredicate (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                         Check.SourceAndKeySelector (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                         Check.SourceAndKeyElementSelectors (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                         Check.JoinSelectors (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                         Check.FirstAndSecond (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                         Check.JoinSelectors (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                         Check.Source (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                         Check.SourceAndPredicate (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                         Check.Source (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                         Check.SourceAndPredicate (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                         Check.Source (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                         Check.SourceAndSelector (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                         Check.Source (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                         Check.Source (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                         Check.Source (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                         Check.SourceAndSelector (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                 static U? IterateNullable<T, U> (IEnumerable<T> source, U initialValue, Func<T, U?, U?> selector) where U : struct
1234                 {
1235                         Check.SourceAndSelector (source, selector);
1236
1237                         int counter = 0;
1238                         U? value = initialValue;
1239                         foreach (var element in source) {
1240                                 value = selector (element, value);
1241                                 if (!value.HasValue)
1242                                         continue;
1243
1244                                 ++counter;
1245                         }
1246
1247                         if (counter == 0)
1248                                 return null;
1249                         
1250                         return value;
1251                 }
1252
1253                 public static int? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1254                 {
1255                         return IterateNullable (source, int.MinValue, (a, b) => {
1256                                 var v = selector (a); return v > b ? v : b;
1257                         });
1258                 }
1259
1260                 public static long? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1261                 {
1262                         return IterateNullable (source, long.MinValue, (a, b) => {
1263                                 var v = selector (a); return v > b ? v : b;
1264                         });
1265                 }
1266
1267                 public static double? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1268                 {
1269                         return IterateNullable (source, double.MinValue, (a, b) => {
1270                                 var v = selector (a); return v > b ? v : b;
1271                         });
1272                 }
1273
1274                 public static float? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1275                 {
1276                         return IterateNullable (source, float.MinValue, (a, b) => {
1277                                 var v = selector (a); return v > b ? v : b;
1278                         });
1279                 }
1280
1281                 public static decimal? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1282                 {
1283                         return IterateNullable (source, decimal.MinValue, (a, b) => {
1284                                 var v = selector (a); return v > b ? v : b;
1285                         });
1286                 }
1287
1288                 public static TResult Max<TSource, TResult> (this IEnumerable<TSource> source,
1289                                 Func<TSource, TResult> selector)
1290                 {
1291                         Check.SourceAndSelector (source, selector);
1292
1293                         bool notAssigned = true;
1294                         TResult maximum = default (TResult);
1295                         int counter = 0;
1296                         foreach (TSource item in source) {
1297                                 TResult element = selector (item);
1298                                 if (notAssigned) {
1299                                         maximum = element;
1300                                         notAssigned = false;
1301                                 } else {
1302                                         int comparison;
1303                                         if (element is IComparable<TResult>)
1304                                                 comparison = ((IComparable<TResult>) element).CompareTo (maximum);
1305                                         else if (element is System.IComparable)
1306                                                 comparison = ((System.IComparable) element).CompareTo (maximum);
1307                                         else
1308                                                 throw new ArgumentNullException ();
1309
1310                                         if (comparison > 0)
1311                                                 maximum = element;
1312                                 }
1313                                 counter++;
1314                         }
1315
1316                         if (counter == 0)
1317                                 throw new InvalidOperationException ();
1318                         else
1319                                 return maximum;
1320                 }
1321
1322                 #endregion
1323
1324                 #region Min
1325
1326                 public static int Min (this IEnumerable<int> source)
1327                 {
1328                         return Iterate (source, int.MaxValue, (a, b) => a < b);
1329                 }
1330
1331                 public static long Min (this IEnumerable<long> source)
1332                 {
1333                         return Iterate (source, long.MaxValue, (a, b) => a < b);
1334                 }
1335                 
1336                 public static double Min (this IEnumerable<double> source)
1337                 {
1338                         return Iterate (source, double.MaxValue, (a, b) => a < b);
1339                 }
1340
1341                 public static float Min (this IEnumerable<float> source)
1342                 {
1343                         return Iterate (source, float.MaxValue, (a, b) => a < b);
1344                 }
1345
1346                 public static decimal Min (this IEnumerable<decimal> source)
1347                 {
1348                         return Iterate (source, decimal.MaxValue, (a, b) => a < b);
1349                 }
1350
1351                 public static int? Min (this IEnumerable<int?> source)
1352                 {
1353                         return IterateNullable (source, int.MaxValue, (a, b) => a < b);
1354                 }
1355
1356                 public static long? Min (this IEnumerable<long?> source)
1357                 {
1358                         return IterateNullable (source, long.MaxValue, (a, b) => a < b);
1359                 }
1360                 
1361                 public static double? Min (this IEnumerable<double?> source)
1362                 {
1363                         return IterateNullable (source, double.MaxValue, (a, b) => a < b);
1364                 }
1365
1366                 public static float? Min (this IEnumerable<float?> source)
1367                 {
1368                         return IterateNullable (source, float.MaxValue, (a, b) => a < b);
1369                 }
1370
1371                 public static decimal? Min (this IEnumerable<decimal?> source)
1372                 {
1373                         return IterateNullable (source, decimal.MaxValue, (a, b) => a < b);
1374                 }
1375                 
1376                 public static TSource Min<TSource> (this IEnumerable<TSource> source)
1377                 {
1378                         Check.Source (source);
1379
1380                         bool notAssigned = true;
1381                         TSource minimum = default (TSource);
1382                         int counter = 0;
1383                         foreach (TSource element in source) {
1384                                 if (notAssigned) {
1385                                         minimum = element;
1386                                         notAssigned = false;
1387                                 } else {
1388                                         int comparison;
1389                                         if (element is IComparable<TSource>)
1390                                                 comparison = ((IComparable<TSource>) element).CompareTo (minimum);
1391                                         else if (element is System.IComparable)
1392                                                 comparison = ((System.IComparable) element).CompareTo (minimum);
1393                                         else
1394                                                 throw new ArgumentNullException ();
1395
1396                                         if (comparison < 0)
1397                                                 minimum = element;
1398                                 }
1399                                 counter++;
1400                         }
1401
1402                         if (counter == 0)
1403                                 throw new InvalidOperationException ();
1404                         else
1405                                 return minimum;
1406                 }
1407
1408                 public static int Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1409                 {
1410                         return Iterate (source, int.MaxValue, (a, b) => { 
1411                                 var v = selector (a); return v < b ? v : b;
1412                         });
1413                 }
1414                 
1415                 public static long Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1416                 {
1417                         return Iterate (source, long.MaxValue, (a, b) => { 
1418                                 var v = selector (a); return v < b ? v : b;
1419                         });
1420                 }
1421                 
1422                 public static double Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1423                 {
1424                         return Iterate (source, double.MaxValue, (a, b) => { 
1425                                 var v = selector (a); return v < b ? v : b;
1426                         });
1427                 }
1428                 
1429                 public static float Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1430                 {
1431                         return Iterate (source, float.MaxValue, (a, b) => { 
1432                                 var v = selector (a); return v < b ? v : b;
1433                         });
1434                 }
1435                 
1436                 public static decimal Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1437                 {
1438                         return Iterate (source, decimal.MaxValue, (a, b) => { 
1439                                 var v = selector (a); return v < b ? v : b;
1440                         });
1441                 }
1442
1443                 public static int? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1444                 {
1445                         return IterateNullable (source, int.MaxValue, (a, b) => { 
1446                                 var v = selector (a); return v < b ? v : b;
1447                         });
1448                 }
1449
1450                 public static long? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1451                 {
1452                         return IterateNullable (source, long.MaxValue, (a, b) => { 
1453                                 var v = selector (a); return v < b ? v : b;
1454                         });
1455                 }
1456
1457                 public static double? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1458                 {
1459                         return IterateNullable (source, float.MaxValue, (a, b) => { 
1460                                 var v = selector (a); return v < b ? v : b;
1461                         });
1462                 }
1463
1464                 public static double? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1465                 {
1466                         return IterateNullable (source, double.MaxValue, (a, b) => { 
1467                                 var v = selector (a); return v < b ? v : b;
1468                         });
1469                 }
1470
1471                 public static decimal? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1472                 {
1473                         return IterateNullable (source, decimal.MaxValue, (a, b) => { 
1474                                 var v = selector (a); return v < b ? v : b;
1475                         });
1476                 }
1477
1478                 public static TResult Min<TSource, TResult> (this IEnumerable<TSource> source,
1479                                 Func<TSource, TResult> selector)
1480                 {
1481                         Check.SourceAndSelector (source, selector);
1482
1483                         bool notAssigned = true;
1484                         TResult minimum = default (TResult);
1485                         int counter = 0;
1486                         foreach (TSource item in source) {
1487                                 TResult element = selector (item);
1488                                 if (notAssigned) {
1489                                         minimum = element;
1490                                         notAssigned = false;
1491                                 } else {
1492                                         int comparison;
1493                                         if (element is IComparable<TResult>)
1494                                                 comparison = ((IComparable<TResult>) element).CompareTo (minimum);
1495                                         else if (element is System.IComparable)
1496                                                 comparison = ((System.IComparable) element).CompareTo (minimum);
1497                                         else
1498                                                 throw new ArgumentNullException ();
1499
1500                                         if (comparison < 0)
1501                                                 minimum = element;
1502                                 }
1503                                 counter++;
1504                         }
1505
1506                         if (counter == 0)
1507                                 throw new InvalidOperationException ();
1508                         else
1509                                 return minimum;
1510                 }
1511
1512                 #endregion
1513
1514                 #region OfType
1515
1516                 public static IEnumerable<TResult> OfType<TResult> (this IEnumerable source)
1517                 {
1518                         Check.Source (source);
1519
1520                         foreach (object element in source)
1521                                 if (element is TResult)
1522                                         yield return (TResult) element;
1523                 }
1524
1525                 #endregion
1526
1527                 #region OrderBy
1528
1529                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
1530                                 Func<TSource, TKey> keySelector)
1531                 {
1532                         return OrderBy<TSource, TKey> (source, keySelector, null);
1533                 }
1534
1535
1536                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
1537                                 Func<TSource, TKey> keySelector,
1538                                 IComparer<TKey> comparer)
1539                 {
1540                         Check.SourceAndKeySelector (source, keySelector);
1541
1542                         return new InternalOrderedSequence<TSource, TKey> (
1543                                         source, keySelector, comparer, false);
1544                 }
1545
1546                 #endregion
1547
1548                 #region OrderByDescending
1549
1550                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
1551                                 Func<TSource, TKey> keySelector)
1552                 {
1553                         return OrderByDescending<TSource, TKey> (source, keySelector, null);
1554                 }
1555
1556
1557                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
1558                                 Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
1559                 {
1560                         Check.SourceAndKeySelector (source, keySelector);
1561
1562                         return new InternalOrderedSequence<TSource, TKey> (
1563                                         source, keySelector, comparer, true);
1564                 }
1565
1566                 #endregion
1567
1568                 #region Range
1569
1570                 public static IEnumerable<int> Range (int start, int count)
1571                 {
1572                         int upto = (start + count - 1);
1573
1574                         if (count < 0 || upto > int.MaxValue)
1575                                 throw new ArgumentOutOfRangeException ();
1576
1577                         for (int i = start; i <= upto; i++)
1578                                 yield return i;
1579                 }
1580
1581                 #endregion
1582
1583                 #region Repeat
1584
1585                 public static IEnumerable<TResult> Repeat<TResult> (TResult element, int count)
1586                 {
1587                         if (count < 0)
1588                                 throw new ArgumentOutOfRangeException ();
1589
1590                         for (int i = 0; i < count; i++)
1591                                 yield return element;
1592                 }
1593
1594                 #endregion
1595
1596
1597                 #region Reverse
1598
1599                 public static IEnumerable<TSource> Reverse<TSource> (this IEnumerable<TSource> source)
1600                 {
1601                         Check.Source (source);
1602
1603                         List<TSource> list = new List<TSource> (source);
1604                         list.Reverse ();
1605                         return list;
1606                 }
1607
1608                 #endregion
1609
1610                 #region Select
1611
1612                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source,
1613                                 Func<TSource, TResult> selector)
1614                 {
1615                         Check.SourceAndSelector (source, selector);
1616
1617                         foreach (TSource element in source)
1618                                 yield return selector (element);
1619                 }
1620
1621                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source,
1622                                 Func<TSource, int, TResult> selector)
1623                 {
1624                         Check.SourceAndSelector (source, selector);
1625
1626                         int counter = 0;
1627                         foreach (TSource element in source) {
1628                                 yield return selector (element, counter);
1629                                 counter++;
1630                         }
1631                 }
1632
1633                 #endregion
1634
1635                 #region SelectMany
1636
1637                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source,
1638                                 Func<TSource, IEnumerable<TResult>> selector)
1639                 {
1640                         Check.SourceAndSelector (source, selector);
1641
1642                         foreach (TSource element in source)
1643                                 foreach (TResult item in selector (element))
1644                                         yield return item;
1645                 }
1646
1647
1648                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source,
1649                                 Func<TSource, int, IEnumerable<TResult>> selector)
1650                 {
1651                         Check.SourceAndSelector (source, selector);
1652
1653                         int counter = 0;
1654                         foreach (TSource element in source) {
1655                                 foreach (TResult item in selector (element, counter++))
1656                                         yield return item;
1657                                 counter++;
1658                         }
1659                 }
1660
1661                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
1662                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1663                 {
1664                         Check.SourceAndCollectionSelectors (source, collectionSelector, selector);
1665
1666                         foreach (TSource element in source)
1667                                 foreach (TCollection collection in collectionSelector (element))
1668                                         yield return selector (element, collection);
1669                 }
1670
1671                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
1672                 Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1673                 {
1674                         Check.SourceAndCollectionSelectors (source, collectionSelector, selector);
1675
1676                         int counter = 0;
1677                         foreach (TSource element in source)
1678                                 foreach (TCollection collection in collectionSelector (element, counter++))
1679                                         yield return selector (element, collection);
1680                 }
1681
1682                 #endregion
1683
1684                 #region Single
1685
1686                 public static TSource Single<TSource> (this IEnumerable<TSource> source)
1687                 {
1688                         Check.Source (source);
1689
1690                         bool otherElement = false;
1691                         TSource singleElement = default (TSource);
1692                         foreach (TSource element in source) {
1693                                 if (otherElement) throw new InvalidOperationException ();
1694                                 if (!otherElement) otherElement = true;
1695                                 singleElement = element;
1696                         }
1697
1698                         if (otherElement)
1699                                 return singleElement;
1700                         else
1701                                 throw new InvalidOperationException ();
1702                 }
1703
1704
1705                 public static TSource Single<TSource> (this IEnumerable<TSource> source,
1706                                 Func<TSource, bool> predicate)
1707                 {
1708                         Check.SourceAndPredicate (source, predicate);
1709
1710                         bool otherElement = false;
1711                         TSource singleElement = default (TSource);
1712                         foreach (TSource element in source) {
1713                                 if (predicate (element)) {
1714                                         if (otherElement) throw new InvalidOperationException ();
1715                                         if (!otherElement) otherElement = true;
1716                                         singleElement = element;
1717                                 }
1718                         }
1719
1720                         if (otherElement)
1721                                 return singleElement;
1722                         else
1723                                 throw new InvalidOperationException ();
1724                 }
1725
1726                 #endregion
1727
1728                 #region SingleOrDefault
1729
1730                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source)
1731                 {
1732                         Check.Source (source);
1733
1734                         bool otherElement = false;
1735                         TSource singleElement = default (TSource);
1736                         foreach (TSource element in source) {
1737                                 if (otherElement) throw new InvalidOperationException ();
1738                                 if (!otherElement) otherElement = true;
1739                                 singleElement = element;
1740                         }
1741
1742                         return singleElement;
1743                 }
1744
1745
1746                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source,
1747                                 Func<TSource, bool> predicate)
1748                 {
1749                         Check.SourceAndPredicate (source, predicate);
1750
1751                         bool otherElement = false;
1752                         TSource singleElement = default (TSource);
1753                         foreach (TSource element in source) {
1754                                 if (predicate (element)) {
1755                                         if (otherElement) throw new InvalidOperationException ();
1756                                         if (!otherElement) otherElement = true;
1757                                         singleElement = element;
1758                                 }
1759                         }
1760
1761                         return singleElement;
1762                 }
1763
1764                 #endregion
1765
1766                 #region Skip
1767                 public static IEnumerable<TSource> Skip<TSource> (this IEnumerable<TSource> source, int count)
1768                 {
1769                         Check.Source (source);
1770
1771                         int i = 0;
1772                         foreach (var element in source) {
1773                                 if (i++ < count)
1774                                         continue;
1775
1776                                 yield return element;
1777                         }
1778                 }
1779                 #endregion
1780
1781                 #region SkipWhile
1782
1783
1784                 public static IEnumerable<TSource> SkipWhile<TSource> (
1785                                 this IEnumerable<TSource> source,
1786                                 Func<TSource, bool> predicate)
1787                 {
1788                         Check.SourceAndPredicate (source, predicate);
1789
1790                         bool yield = false;
1791
1792                         foreach (TSource element in source) {
1793                                 if (yield)
1794                                         yield return element;
1795                                 else
1796                                         if (!predicate (element)) {
1797                                                 yield return element;
1798                                                 yield = true;
1799                                         }
1800                         }
1801                 }
1802
1803                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source,
1804                                 Func<TSource, int, bool> predicate)
1805                 {
1806                         Check.SourceAndPredicate (source, predicate);
1807
1808                         int counter = 0;
1809                         bool yield = false;
1810
1811                         foreach (TSource element in source) {
1812                                 if (yield)
1813                                         yield return element;
1814                                 else
1815                                         if (!predicate (element, counter)) {
1816                                                 yield return element;
1817                                                 yield = true;
1818                                         }
1819                                 counter++;
1820                         }
1821                 }
1822
1823                 #endregion
1824
1825                 #region Sum
1826
1827                 public static int Sum (this IEnumerable<int> source)
1828                 {
1829                         return Sum<int, int> (source, (a, b) => a + b);
1830                 }
1831                 
1832                 public static int? Sum (this IEnumerable<int?> source)
1833                 {
1834                         return SumNullable<int?, int?> (source, (a, b) => a.HasValue ? a + b : a);
1835                 }
1836                 
1837                 public static int Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1838                 {
1839                         return Sum<TSource, int> (source, (a, b) => a + selector (b));
1840                 }
1841                 
1842                 public static int? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1843                 {
1844                         return SumNullable<TSource, int?> (source, (a, b) => { 
1845                                 var value = selector (b);
1846                                 return value.HasValue ? a + value.Value : a;
1847                         });
1848                 }
1849                 
1850                 public static long Sum (this IEnumerable<long> source)
1851                 {
1852                         return Sum<long, long> (source, (a, b) => a + b);
1853                 }
1854                 
1855                 public static long? Sum (this IEnumerable<long?> source)
1856                 {
1857                         return SumNullable<long?, long?> (source, (a, b) => a.HasValue ? a + b : a);
1858                 }               
1859                 
1860                 public static long Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1861                 {
1862                         return Sum<TSource, long> (source, (a, b) => a + selector (b));
1863                 }
1864                 
1865                 public static long? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1866                 {
1867                         return SumNullable<TSource, long?> (source, (a, b) => { 
1868                                 var value = selector (b);
1869                                 return value.HasValue ? a + value.Value : a;
1870                         });
1871                 }       
1872                 
1873                 public static double Sum (this IEnumerable<double> source)
1874                 {
1875                         return Sum<double, double> (source, (a, b) => a + b);
1876                 }
1877                 
1878                 public static double? Sum (this IEnumerable<double?> source)
1879                 {
1880                         return SumNullable<double?, double?> (source, (a, b) => a.HasValue ? a + b : a);
1881                 }
1882                 
1883                 public static double Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1884                 {
1885                         return Sum<TSource, double> (source, (a, b) => a + selector (b));
1886                 }
1887                 
1888                 public static double? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1889                 {
1890                         return SumNullable<TSource, double?> (source, (a, b) => { 
1891                                 var value = selector (b);
1892                                 return value.HasValue ? a + value.Value : a;
1893                         });
1894                 }       
1895                 
1896                 public static float Sum (this IEnumerable<float> source)
1897                 {
1898                         return Sum<float, float> (source, (a, b) => a + b);
1899                 }
1900                 
1901                 public static float? Sum (this IEnumerable<float?> source)
1902                 {
1903                         return SumNullable<float?, float?> (source, (a, b) => a.HasValue ? a + b : a);
1904                 }               
1905                 
1906                 public static float Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1907                 {
1908                         return Sum<TSource, float> (source, (a, b) => a + selector (b));
1909                 }
1910                 
1911                 public static float? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1912                 {
1913                         return SumNullable<TSource, float?> (source, (a, b) => { 
1914                                 var value = selector (b);
1915                                 return value.HasValue ? a + value.Value : a;
1916                         });
1917                 }               
1918                 
1919                 public static decimal Sum (this IEnumerable<decimal> source)
1920                 {
1921                         return Sum<decimal, decimal> (source, (a, b) => a + b);
1922                 }
1923                 
1924                 public static decimal? Sum (this IEnumerable<decimal?> source)
1925                 {
1926                         return SumNullable<decimal?, decimal?> (source, (a, b) => a.HasValue ? a + b : a);
1927                 }               
1928                 
1929                 public static decimal Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1930                 {
1931                         return Sum<TSource, decimal> (source, (a, b) => a + selector (b));
1932                 }
1933                 
1934                 public static decimal? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1935                 {
1936                         return SumNullable<TSource, decimal?> (source, (a, b) => { 
1937                                 var value = selector (b);
1938                                 return value.HasValue ? a + value.Value : a;
1939                         });
1940                 }               
1941                 
1942                 static TR Sum<TA, TR> (this IEnumerable<TA> source, Func<TR, TA, TR> func)
1943                 {
1944                         Check.Source (source);
1945
1946                         TR total = default (TR);
1947                         int counter = 0;
1948                         foreach (var element in source) {
1949                                 total = func (total, element);
1950                                 ++counter;
1951                         }
1952
1953                         if (counter == 0)
1954                                 throw new InvalidOperationException ();
1955                                 
1956                         return total;
1957                 }
1958                 
1959                 static TR SumNullable<TA, TR> (this IEnumerable<TA> source, Func<TR, TA, TR> func)
1960                 {
1961                         Check.Source (source);
1962
1963                         TR total = default (TR);
1964                         foreach (var element in source) {
1965                                 total = func (total, element);
1966                         }
1967
1968                         return total;
1969                 }
1970
1971                 #endregion
1972
1973                 #region Take
1974
1975                 public static IEnumerable<TSource> Take<TSource> (this IEnumerable<TSource> source, int count)
1976                 {
1977                         Check.Source (source);
1978
1979                         if (count <= 0)
1980                                 yield break;
1981
1982                         int counter = 0;
1983                         foreach (TSource element in source) {
1984                                 if (counter++ == count)
1985                                         yield break;
1986
1987                                 yield return element;
1988                         }
1989                 }
1990
1991                 #endregion
1992
1993                 #region TakeWhile
1994
1995                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1996                 {
1997                         Check.SourceAndPredicate (source, predicate);
1998
1999                         foreach (TSource element in source) {
2000                                 if (!predicate (element))
2001                                         yield break;
2002
2003                                 yield return element;
2004                         }
2005                 }
2006
2007                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2008                 {
2009                         Check.SourceAndPredicate (source, predicate);
2010
2011                         int counter = 0;
2012                         foreach (var element in source) {
2013                                 if (!predicate (element, counter))
2014                                         yield break;
2015
2016                                 yield return element;
2017                                 counter++;
2018                         }
2019                 }
2020
2021                 #endregion
2022
2023                 #region ThenBy
2024
2025                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2026                 {
2027                         return ThenBy<TSource, TKey> (source, keySelector, null);
2028                 }
2029
2030
2031                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2032                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2033                 {
2034                         Check.SourceAndKeySelector (source, keySelector);
2035
2036                         return source.CreateOrderedEnumerable (keySelector, comparer, false);
2037                 }
2038
2039                 #endregion
2040
2041                 #region ThenByDescending
2042
2043                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2044                         Func<TSource, TKey> keySelector)
2045                 {
2046                         return ThenByDescending<TSource, TKey> (source, keySelector, null);
2047                 }
2048
2049
2050                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2051                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2052                 {
2053                         Check.SourceAndKeySelector (source, keySelector);
2054
2055                         return source.CreateOrderedEnumerable (keySelector, comparer, true);
2056                 }
2057
2058                 #endregion
2059
2060                 #region ToArray
2061                 public static TSource [] ToArray<TSource> (this IEnumerable<TSource> source)
2062                 {
2063                         Check.Source (source);
2064
2065                         List<TSource> list = new List<TSource> (source);
2066                         return list.ToArray ();
2067                 }
2068
2069                 #endregion
2070
2071                 #region ToDictionary
2072                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2073                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2074                 {
2075                         return ToDictionary<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2076                 }
2077
2078                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2079                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2080                 {
2081                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2082
2083                         var dict = new Dictionary<TKey, TElement> (comparer);
2084                         foreach (var e in source)
2085                                 dict.Add (keySelector (e), elementSelector (e));
2086
2087                         return dict;
2088                 }
2089                 
2090                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2091                                 Func<TSource, TKey> keySelector)
2092                 {
2093                         return ToDictionary (source, keySelector, null);
2094                 }
2095
2096                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2097                                 Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2098                 {
2099                         throw new NotImplementedException ();
2100                         // FIXME: compiler issue
2101                         //return ToDictionary (source, keySelector, (a) => a, comparer);
2102                 }
2103                 
2104                 #endregion
2105
2106                 #region ToList
2107                 public static List<TSource> ToList<TSource> (this IEnumerable<TSource> source)
2108                 {
2109                         Check.Source (source);
2110
2111                         return new List<TSource> (source);
2112                 }
2113                 #endregion
2114
2115                 #region ToLookup
2116
2117                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2118                 {
2119                         return ToLookup<TSource, TKey> (source, keySelector, null);
2120                 }
2121
2122                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source,
2123                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2124                 {
2125                         Check.SourceAndKeySelector (source, keySelector);
2126
2127                         var dictionary = new Dictionary<TKey, List<TSource>> (comparer ?? EqualityComparer<TKey>.Default);
2128                         foreach (TSource element in source) {
2129                                 TKey key = keySelector (element);
2130                                 if (key == null)
2131                                         throw new ArgumentNullException ();
2132                                 if (!dictionary.ContainsKey (key))
2133                                         dictionary.Add (key, new List<TSource> ());
2134                                 dictionary [key].Add (element);
2135                         }
2136                         return new Lookup<TKey, TSource> (dictionary);
2137                 }
2138
2139                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2140                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2141                 {
2142                         return ToLookup<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2143                 }
2144
2145                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2146                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2147                 {
2148                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2149
2150                         Dictionary<TKey, List<TElement>> dictionary = new Dictionary<TKey, List<TElement>> (comparer ?? EqualityComparer<TKey>.Default);
2151                         foreach (TSource element in source) {
2152                                 TKey key = keySelector (element);
2153                                 if (key == null)
2154                                         throw new ArgumentNullException ();
2155                                 if (!dictionary.ContainsKey (key))
2156                                         dictionary.Add (key, new List<TElement> ());
2157                                 dictionary [key].Add (elementSelector (element));
2158                         }
2159                         return new Lookup<TKey, TElement> (dictionary);
2160                 }
2161
2162                 #endregion
2163
2164                 #region SequenceEqual
2165
2166                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2167                 {
2168                         return first.SequenceEqual (second, null);
2169                 }
2170
2171                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2172                 {
2173                         Check.FirstAndSecond (first, second);
2174
2175                         if (comparer == null)
2176                                 comparer = EqualityComparer<TSource>.Default;
2177
2178                         var first_enumerator = first.GetEnumerator ();
2179                         var second_enumerator = second.GetEnumerator ();
2180
2181                         while (first_enumerator.MoveNext ()) {
2182                                 if (!second_enumerator.MoveNext ())
2183                                         return false;
2184
2185                                 if (!comparer.Equals (first_enumerator.Current, second_enumerator.Current))
2186                                         return false;
2187                         }
2188
2189                         return !second_enumerator.MoveNext ();
2190                 }
2191
2192                 #endregion
2193
2194                 #region Union
2195
2196                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2197                 {
2198                         Check.FirstAndSecond (first, second);
2199
2200                         return first.Union (second, null);
2201                 }
2202
2203                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2204                 {
2205                         Check.FirstAndSecond (first, second);
2206
2207                         if (comparer == null)
2208                                 comparer = EqualityComparer<TSource>.Default;
2209
2210                         var items = new List<TSource> (); // TODO: use a HashSet here
2211                         foreach (var element in first) {
2212                                 if (! items.Contains (element, comparer)) {
2213                                         items.Add (element);
2214                                         yield return element;
2215                                 }
2216                         }
2217
2218                         foreach (var element in second) {
2219                                 if (! items.Contains (element, comparer)) {
2220                                         items.Add (element);
2221                                         yield return element;
2222                                 }
2223                         }
2224                 }
2225
2226                 #endregion
2227
2228                 #region Where
2229
2230                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source,
2231                                 Func<TSource, bool> predicate)
2232                 {
2233                         Check.SourceAndPredicate (source, predicate);
2234
2235                         foreach (TSource element in source)
2236                                 if (predicate (element))
2237                                         yield return element;
2238                 }
2239
2240
2241                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source,
2242                                 Func<TSource, int, bool> predicate)
2243                 {
2244                         Check.SourceAndPredicate (source, predicate);
2245
2246                         int counter = 0;
2247                         foreach (TSource element in source) {
2248                                 if (predicate (element, counter))
2249                                         yield return element;
2250                                 counter++;
2251                         }
2252                 }
2253
2254                 #endregion
2255
2256                 // These methods are not included in the
2257                 // .NET Standard Query Operators Specification,
2258                 // but they provide additional useful commands
2259
2260                 #region ToReadOnlyCollection
2261                 internal static ReadOnlyCollection<TSource> ToReadOnlyCollection<TSource> (IEnumerable<TSource> source)
2262                 {
2263                         if (source == null)
2264                                 return new ReadOnlyCollection<TSource> (new List<TSource> ());
2265
2266                         if (typeof (ReadOnlyCollection<TSource>).IsInstanceOfType (source))
2267                                 return source as ReadOnlyCollection<TSource>;
2268
2269                         return new ReadOnlyCollection<TSource> (ToArray<TSource> (source));
2270                 }
2271                 #endregion
2272         }
2273 }