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