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