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