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