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