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