3ac3fc5a4a2c0798b9c5d01949ff5c44e831ec63
[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                         return source.First (PredicateOf<TSource>.Always, Fallback.Throw);
583                 }
584
585                 public static TSource First<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
586                 {
587                         Check.SourceAndPredicate (source, predicate);
588
589                         return source.First (predicate, Fallback.Throw);
590                 }
591
592                 #endregion
593
594                 #region FirstOrDefault
595
596                 public static TSource FirstOrDefault<TSource> (this IEnumerable<TSource> source)
597                 {
598                         Check.Source (source);
599
600                         return source.First (PredicateOf<TSource>.Always, Fallback.Default);
601                 }
602
603                 public static TSource FirstOrDefault<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
604                 {
605                         Check.SourceAndPredicate (source, predicate);
606
607                         return source.First (predicate, Fallback.Default);
608                 }
609
610                 #endregion
611
612                 #region GroupBy
613
614                 private static List<T> ContainsGroup<K, T> (
615                                 Dictionary<K, List<T>> items, K key, IEqualityComparer<K> comparer)
616                 {
617                         IEqualityComparer<K> comparerInUse = (comparer ?? EqualityComparer<K>.Default);
618                         foreach (KeyValuePair<K, List<T>> value in items) {
619                                 if (comparerInUse.Equals (value.Key, key))
620                                         return value.Value;
621                         }
622                         return null;
623                 }
624
625                 public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this IEnumerable<TSource> source,
626                         Func<TSource, TKey> keySelector)
627                 {
628                         return GroupBy<TSource, TKey> (source, keySelector, null);
629                 }
630
631                 public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this IEnumerable<TSource> source,
632                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
633                 {
634                         Check.SourceAndKeySelector (source, keySelector);
635
636                         return CreateGroupByIterator (source, keySelector, comparer);
637                 }
638
639                 static IEnumerable<IGrouping<TKey, TSource>> CreateGroupByIterator<TSource, TKey> (this IEnumerable<TSource> source,
640                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
641                 {
642                         Dictionary<TKey, List<TSource>> groups = new Dictionary<TKey, List<TSource>> ();
643                         List<TSource> nullList = new List<TSource> ();
644                         int counter = 0;
645                         int nullCounter = -1;
646
647                         foreach (TSource element in source) {
648                                 TKey key = keySelector (element);
649                                 if (key == null) {
650                                         nullList.Add (element);
651                                         if (nullCounter == -1) {
652                                                 nullCounter = counter;
653                                                 counter++;
654                                         }
655                                 } else {
656                                         List<TSource> group = ContainsGroup<TKey, TSource> (groups, key, comparer);
657                                         if (group == null) {
658                                                 group = new List<TSource> ();
659                                                 groups.Add (key, group);
660                                                 counter++;
661                                         }
662                                         group.Add (element);
663                                 }
664                         }
665
666                         counter = 0;
667                         foreach (KeyValuePair<TKey, List<TSource>> group in groups) {
668                                 if (counter == nullCounter) {
669                                         Grouping<TKey, TSource> nullGroup = new Grouping<TKey, TSource> (default (TKey), nullList);
670                                         yield return nullGroup;
671                                         counter++;
672                                 }
673                                 Grouping<TKey, TSource> grouping = new Grouping<TKey, TSource> (group.Key, group.Value);
674                                 yield return grouping;
675                                 counter++;
676                         }
677                 }
678
679                 public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this IEnumerable<TSource> source,
680                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
681                 {
682                         return GroupBy<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
683                 }
684
685                 public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this IEnumerable<TSource> source,
686                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
687                 {
688                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
689
690                         Dictionary<TKey, List<TElement>> groups = new Dictionary<TKey, List<TElement>> ();
691                         List<TElement> nullList = new List<TElement> ();
692                         int counter = 0;
693                         int nullCounter = -1;
694
695                         foreach (TSource item in source) {
696                                 TKey key = keySelector (item);
697                                 TElement element = elementSelector (item);
698                                 if (key == null) {
699                                         nullList.Add (element);
700                                         if (nullCounter == -1) {
701                                                 nullCounter = counter;
702                                                 counter++;
703                                         }
704                                 } else {
705                                         List<TElement> group = ContainsGroup<TKey, TElement> (groups, key, comparer);
706                                         if (group == null) {
707                                                 group = new List<TElement> ();
708                                                 groups.Add (key, group);
709                                                 counter++;
710                                         }
711                                         group.Add (element);
712                                 }
713                         }
714
715                         counter = 0;
716                         foreach (KeyValuePair<TKey, List<TElement>> group in groups) {
717                                 if (counter == nullCounter) {
718                                         Grouping<TKey, TElement> nullGroup = new Grouping<TKey, TElement> (default (TKey), nullList);
719                                         yield return nullGroup;
720                                         counter++;
721                                 }
722                                 Grouping<TKey, TElement> grouping = new Grouping<TKey, TElement> (group.Key, group.Value);
723                                 yield return grouping;
724                                 counter++;
725                         }
726                 }
727
728                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult> (this IEnumerable<TSource> source,
729                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector,
730                         Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
731                 {
732                         return GroupBy (source, keySelector, elementSelector, resultSelector, null);
733                 }
734
735                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult> (this IEnumerable<TSource> source,
736                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector,
737                         Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
738                         IEqualityComparer<TKey> comparer)
739                 {
740                         IEnumerable<IGrouping<TKey, TElement>> groups = GroupBy<TSource, TKey, TElement> (
741                                 source, keySelector, elementSelector, comparer);
742
743                         foreach (IGrouping<TKey, TElement> group in groups)
744                                 yield return resultSelector (group.Key, group);
745                 }
746
747                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult> (this IEnumerable<TSource> source,
748                         Func<TSource, TKey> keySelector,
749                         Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
750                 {
751                         return GroupBy (source, keySelector, resultSelector, null);
752                 }
753
754                 public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult> (this IEnumerable<TSource> source,
755                         Func<TSource, TKey> keySelector,
756                         Func<TKey, IEnumerable<TSource>, TResult> resultSelector,
757                         IEqualityComparer<TKey> comparer)
758                 {
759                         IEnumerable<IGrouping<TKey,TSource>> groups = GroupBy<TSource, TKey> (source, keySelector, comparer);
760
761                         foreach (IGrouping<TKey, TSource> group in groups)
762                                 yield return resultSelector (group.Key, group);
763                 }
764
765                 #endregion
766
767                 # region GroupJoin
768
769                 public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
770                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
771                         Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
772                 {
773                         return GroupJoin (outer, inner, outerKeySelector, innerKeySelector, resultSelector, null);
774                 }
775
776                 public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
777                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
778                         Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
779                         IEqualityComparer<TKey> comparer)
780                 {
781                         Check.JoinSelectors (outer, inner, outerKeySelector, innerKeySelector, resultSelector);
782
783                         if (comparer == null)
784                                 comparer = EqualityComparer<TKey>.Default;
785
786                         return CreateGroupJoinIterator (outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
787                 }
788
789                 static IEnumerable<TResult> CreateGroupJoinIterator<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                         ILookup<TKey, TInner> innerKeys = ToLookup<TInner, TKey> (inner, innerKeySelector, comparer);
795                         /*Dictionary<K, List<U>> innerKeys = new Dictionary<K, List<U>> ();
796                         foreach (U element in inner)
797                         {
798                                         K innerKey = innerKeySelector (element);
799                                         if (!innerKeys.ContainsKey (innerKey))
800                                                         innerKeys.Add (innerKey, new List<U> ());
801                                         innerKeys[innerKey].Add (element);
802                         }*/
803
804                         foreach (TOuter element in outer) {
805                                 TKey outerKey = outerKeySelector (element);
806                                 if (innerKeys.Contains (outerKey))
807                                         yield return resultSelector (element, innerKeys [outerKey]);
808                                 else
809                                         yield return resultSelector (element, Empty<TInner> ());
810                         }
811                 }
812
813                 #endregion
814
815                 #region Intersect
816
817                 public static IEnumerable<TSource> Intersect<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
818                 {
819                         return Intersect (first, second, null);
820                 }
821
822                 public static IEnumerable<TSource> Intersect<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
823                 {
824                         Check.FirstAndSecond (first, second);
825
826                         if (comparer == null)
827                                 comparer = EqualityComparer<TSource>.Default;
828
829                         return CreateIntersectIterator (first, second, comparer);
830                 }
831
832                 static IEnumerable<TSource> CreateIntersectIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
833                 {
834                         var items = new HashSet<TSource> (second, comparer);
835                         foreach (TSource element in first) {
836                                 if (items.Contains (element))
837                                         yield return element;
838                         }
839                 }
840
841                 #endregion
842
843                 # region Join
844
845                 public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
846                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
847                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
848                 {
849                         Check.JoinSelectors (outer, inner, outerKeySelector, innerKeySelector, resultSelector);
850
851                         if (comparer == null)
852                                 comparer = EqualityComparer<TKey>.Default;
853
854                         return CreateJoinIterator (outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
855                 }
856
857                 static IEnumerable<TResult> CreateJoinIterator<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
858                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
859                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
860                 {
861                         ILookup<TKey, TInner> innerKeys = ToLookup<TInner, TKey> (inner, innerKeySelector, comparer);
862                         /*Dictionary<K, List<U>> innerKeys = new Dictionary<K, List<U>> ();
863                         foreach (U element in inner)
864                         {
865                                         K innerKey = innerKeySelector (element);
866                                         if (!innerKeys.ContainsKey (innerKey))
867                                                         innerKeys.Add (innerKey, new List<U> ());
868                                         innerKeys[innerKey].Add (element);
869                         }*/
870
871                         foreach (TOuter element in outer) {
872                                 TKey outerKey = outerKeySelector (element);
873                                 if (innerKeys.Contains (outerKey)) {
874                                         foreach (TInner innerElement in innerKeys [outerKey])
875                                                 yield return resultSelector (element, innerElement);
876                                 }
877                         }
878                 }
879
880                 public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult> (this IEnumerable<TOuter> outer,
881                         IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector,
882                         Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector)
883                 {
884                         return outer.Join (inner, outerKeySelector, innerKeySelector, resultSelector, null);
885                 }
886
887                 #endregion
888
889                 #region Last
890
891                 static TSource Last<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate, Fallback fallback)
892                 {
893                         var empty = true;
894                         var item = default (TSource);
895
896                         foreach (var element in source) {
897                                 if (!predicate (element))
898                                         continue;
899
900                                 item = element;
901                                 empty = false;
902                         }
903
904                         if (!empty)
905                                 return item;
906
907                         if (fallback == Fallback.Throw)
908                                 throw new InvalidOperationException ();
909
910                         return item;
911                 }
912
913                 public static TSource Last<TSource> (this IEnumerable<TSource> source)
914                 {
915                         Check.Source (source);
916
917                         return source.Last (PredicateOf<TSource>.Always, Fallback.Throw);
918                 }
919
920                 public static TSource Last<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
921                 {
922                         Check.SourceAndPredicate (source, predicate);
923
924                         return source.Last (predicate, Fallback.Throw);
925                 }
926
927                 #endregion
928
929                 #region LastOrDefault
930
931                 public static TSource LastOrDefault<TSource> (this IEnumerable<TSource> source)
932                 {
933                         Check.Source (source);
934
935                         var list = source as IList<TSource>;
936                         if (list != null)
937                                 return list.Count > 0 ? list [list.Count - 1] : default (TSource);
938
939                         return source.Last (PredicateOf<TSource>.Always, Fallback.Default);
940                 }
941
942                 public static TSource LastOrDefault<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
943                 {
944                         Check.SourceAndPredicate (source, predicate);
945
946                         return source.Last (predicate, Fallback.Default);
947                 }
948
949                 #endregion
950
951                 #region LongCount
952
953                 public static long LongCount<TSource> (this IEnumerable<TSource> source)
954                 {
955                         Check.Source (source);
956
957 #if !NET_2_1
958                         var array = source as TSource [];
959                         if (array != null)
960                                 return array.LongLength;
961 #endif
962
963                         long counter = 0;
964                         using (var enumerator = source.GetEnumerator ())
965                                 while (enumerator.MoveNext ())
966                                         counter++;
967
968                         return counter;
969                 }
970
971                 public static long LongCount<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> selector)
972                 {
973                         Check.SourceAndSelector (source, selector);
974
975                         long counter = 0;
976                         foreach (TSource element in source)
977                                 if (selector (element))
978                                         counter++;
979
980                         return counter;
981                 }
982
983                 #endregion
984
985                 #region Max
986
987                 public static int Max (this IEnumerable<int> source)
988                 {
989                         Check.Source (source);
990
991                         return Iterate (source, int.MinValue, (a, b) => Math.Max (a, b));
992                 }
993
994                 public static long Max (this IEnumerable<long> source)
995                 {
996                         Check.Source (source);
997
998                         return Iterate (source, long.MinValue, (a, b) => Math.Max (a, b));
999                 }
1000
1001                 public static double Max (this IEnumerable<double> source)
1002                 {
1003                         Check.Source (source);
1004
1005                         return Iterate (source, double.MinValue, (a, b) => Math.Max (a, b));
1006                 }
1007
1008                 public static float Max (this IEnumerable<float> source)
1009                 {
1010                         Check.Source (source);
1011
1012                         return Iterate (source, float.MinValue, (a, b) => Math.Max (a, b));
1013                 }
1014
1015                 public static decimal Max (this IEnumerable<decimal> source)
1016                 {
1017                         Check.Source (source);
1018
1019                         return Iterate (source, decimal.MinValue, (a, b) => Math.Max (a, b));
1020                 }
1021
1022                 public static int? Max (this IEnumerable<int?> source)
1023                 {
1024                         Check.Source (source);
1025
1026                         return IterateNullable (source, int.MinValue, (a, b) => a > b);
1027                 }
1028
1029                 public static long? Max (this IEnumerable<long?> source)
1030                 {
1031                         Check.Source (source);
1032
1033                         return IterateNullable (source, long.MinValue, (a, b) => a > b);
1034                 }
1035
1036                 public static double? Max (this IEnumerable<double?> source)
1037                 {
1038                         Check.Source (source);
1039
1040                         return IterateNullable (source, double.MinValue, (a, b) => a > b);
1041                 }
1042
1043                 public static float? Max (this IEnumerable<float?> source)
1044                 {
1045                         Check.Source (source);
1046
1047                         return IterateNullable (source, float.MinValue, (a, b) => a > b);
1048                 }
1049
1050                 public static decimal? Max (this IEnumerable<decimal?> source)
1051                 {
1052                         Check.Source (source);
1053
1054                         return IterateNullable (source, decimal.MinValue, (a, b) => a > b);
1055                 }
1056
1057                 static T? IterateNullable<T> (IEnumerable<T?> source, T initValue, Func<T?, T?, bool> selector) where T : struct
1058                 {
1059                         int counter = 0;
1060                         T? value = initValue;
1061                         foreach (var element in source) {
1062                                 if (!element.HasValue)
1063                                         continue;
1064
1065                                 if (selector (element.Value, value))
1066                                         value = element;
1067                                 ++counter;
1068                         }
1069
1070                         if (counter == 0)
1071                                 return null;
1072
1073                         return value;
1074                 }
1075
1076                 public static TSource Max<TSource> (this IEnumerable<TSource> source)
1077                 {
1078                         Check.Source (source);
1079
1080                         bool notAssigned = true;
1081                         TSource maximum = default (TSource);
1082                         int counter = 0;
1083                         foreach (TSource element in source) {
1084                                 if (notAssigned) {
1085                                         maximum = element;
1086                                         notAssigned = false;
1087                                 } else {
1088                                         int comparison;
1089                                         if (element is IComparable<TSource>)
1090                                                 comparison = ((IComparable<TSource>) element).CompareTo (maximum);
1091                                         else if (element is System.IComparable)
1092                                                 comparison = ((System.IComparable) element).CompareTo (maximum);
1093                                         else
1094                                                 throw new ArgumentNullException ();
1095
1096                                         if (comparison > 0)
1097                                                 maximum = element;
1098                                 }
1099                                 counter++;
1100                         }
1101
1102                         if (counter == 0)
1103                                 throw new InvalidOperationException ();
1104                         else
1105                                 return maximum;
1106                 }
1107
1108                 public static int Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1109                 {
1110                         Check.SourceAndSelector (source, selector);
1111
1112                         return Iterate (source, int.MinValue, (a, b) => Math.Max (selector (a), b));
1113                 }
1114
1115                 public static long Max<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1116                 {
1117                         Check.SourceAndSelector (source, selector);
1118
1119                         return Iterate (source, long.MinValue, (a, b) => Math.Max (selector (a), b));
1120                 }
1121
1122                 public static double Max<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1123                 {
1124                         Check.SourceAndSelector (source, selector);
1125
1126                         return Iterate (source, double.MinValue, (a, b) => Math.Max (selector (a), b));
1127                 }
1128
1129                 public static float Max<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1130                 {
1131                         Check.SourceAndSelector (source, selector);
1132
1133                         return Iterate (source, float.MinValue, (a, b) => Math.Max (selector (a), b));
1134                 }
1135
1136                 public static decimal Max<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1137                 {
1138                         Check.SourceAndSelector (source, selector);
1139
1140                         return Iterate (source, decimal.MinValue, (a, b) => Math.Max (selector (a), b));
1141                 }
1142
1143                 static U Iterate<T, U> (IEnumerable<T> source, U initValue, Func<T, U, U> selector)
1144                 {
1145                         int counter = 0;
1146                         foreach (var element in source) {
1147                                 initValue = selector (element, initValue);
1148                                 ++counter;
1149                         }
1150
1151                         if (counter == 0)
1152                                 throw new InvalidOperationException ();
1153
1154                         return initValue;
1155                 }
1156
1157                 static U? IterateNullable<T, U> (IEnumerable<T> source, U initialValue, Func<T, U?, U?> selector) where U : struct
1158                 {
1159                         int counter = 0;
1160                         U? value = initialValue;
1161                         foreach (var element in source) {
1162                                 value = selector (element, value);
1163                                 if (!value.HasValue)
1164                                         continue;
1165
1166                                 ++counter;
1167                         }
1168
1169                         if (counter == 0)
1170                                 return null;
1171
1172                         return value;
1173                 }
1174
1175                 public static int? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1176                 {
1177                         Check.SourceAndSelector (source, selector);
1178
1179                         return IterateNullable (source, int.MinValue, (a, b) => {
1180                                 var v = selector (a); return v > b ? v : b;
1181                         });
1182                 }
1183
1184                 public static long? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1185                 {
1186                         Check.SourceAndSelector (source, selector);
1187
1188                         return IterateNullable (source, long.MinValue, (a, b) => {
1189                                 var v = selector (a); return v > b ? v : b;
1190                         });
1191                 }
1192
1193                 public static double? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1194                 {
1195                         Check.SourceAndSelector (source, selector);
1196
1197                         return IterateNullable (source, double.MinValue, (a, b) => {
1198                                 var v = selector (a); return v > b ? v : b;
1199                         });
1200                 }
1201
1202                 public static float? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1203                 {
1204                         Check.SourceAndSelector (source, selector);
1205
1206                         return IterateNullable (source, float.MinValue, (a, b) => {
1207                                 var v = selector (a); return v > b ? v : b;
1208                         });
1209                 }
1210
1211                 public static decimal? Max<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1212                 {
1213                         Check.SourceAndSelector (source, selector);
1214
1215                         return IterateNullable (source, decimal.MinValue, (a, b) => {
1216                                 var v = selector (a); return v > b ? v : b;
1217                         });
1218                 }
1219
1220                 public static TResult Max<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1221                 {
1222                         Check.SourceAndSelector (source, selector);
1223
1224                         bool notAssigned = true;
1225                         TResult maximum = default (TResult);
1226                         int counter = 0;
1227                         foreach (TSource item in source) {
1228                                 TResult element = selector (item);
1229                                 if (notAssigned) {
1230                                         maximum = element;
1231                                         notAssigned = false;
1232                                 } else {
1233                                         int comparison;
1234                                         if (element is IComparable<TResult>)
1235                                                 comparison = ((IComparable<TResult>) element).CompareTo (maximum);
1236                                         else if (element is System.IComparable)
1237                                                 comparison = ((System.IComparable) element).CompareTo (maximum);
1238                                         else
1239                                                 throw new ArgumentNullException ();
1240
1241                                         if (comparison > 0)
1242                                                 maximum = element;
1243                                 }
1244                                 counter++;
1245                         }
1246
1247                         if (counter == 0)
1248                                 throw new InvalidOperationException ();
1249                         else
1250                                 return maximum;
1251                 }
1252
1253                 #endregion
1254
1255                 #region Min
1256
1257                 public static int Min (this IEnumerable<int> source)
1258                 {
1259                         Check.Source (source);
1260
1261                         return Iterate (source, int.MaxValue, (a, b) => Math.Min (a, b));
1262                 }
1263
1264                 public static long Min (this IEnumerable<long> source)
1265                 {
1266                         Check.Source (source);
1267
1268                         return Iterate (source, long.MaxValue, (a, b) => Math.Min (a, b));
1269                 }
1270
1271                 public static double Min (this IEnumerable<double> source)
1272                 {
1273                         Check.Source (source);
1274
1275                         return Iterate (source, double.MaxValue, (a, b) => Math.Min (a, b));
1276                 }
1277
1278                 public static float Min (this IEnumerable<float> source)
1279                 {
1280                         Check.Source (source);
1281
1282                         return Iterate (source, float.MaxValue, (a, b) => Math.Min (a, b));
1283                 }
1284
1285                 public static decimal Min (this IEnumerable<decimal> source)
1286                 {
1287                         Check.Source (source);
1288
1289                         return Iterate (source, decimal.MaxValue, (a, b) => Math.Min (a, b));
1290                 }
1291
1292                 public static int? Min (this IEnumerable<int?> source)
1293                 {
1294                         Check.Source (source);
1295
1296                         return IterateNullable (source, int.MaxValue, (a, b) => a < b);
1297                 }
1298
1299                 public static long? Min (this IEnumerable<long?> source)
1300                 {
1301                         Check.Source (source);
1302
1303                         return IterateNullable (source, long.MaxValue, (a, b) => a < b);
1304                 }
1305
1306                 public static double? Min (this IEnumerable<double?> source)
1307                 {
1308                         Check.Source (source);
1309
1310                         return IterateNullable (source, double.MaxValue, (a, b) => a < b);
1311                 }
1312
1313                 public static float? Min (this IEnumerable<float?> source)
1314                 {
1315                         Check.Source (source);
1316
1317                         return IterateNullable (source, float.MaxValue, (a, b) => a < b);
1318                 }
1319
1320                 public static decimal? Min (this IEnumerable<decimal?> source)
1321                 {
1322                         Check.Source (source);
1323
1324                         return IterateNullable (source, decimal.MaxValue, (a, b) => a < b);
1325                 }
1326
1327                 public static TSource Min<TSource> (this IEnumerable<TSource> source)
1328                 {
1329                         Check.Source (source);
1330
1331                         bool notAssigned = true;
1332                         TSource minimum = default (TSource);
1333                         int counter = 0;
1334                         foreach (TSource element in source) {
1335                                 if (notAssigned) {
1336                                         minimum = element;
1337                                         notAssigned = false;
1338                                 } else {
1339                                         int comparison;
1340                                         if (element is IComparable<TSource>)
1341                                                 comparison = ((IComparable<TSource>) element).CompareTo (minimum);
1342                                         else if (element is System.IComparable)
1343                                                 comparison = ((System.IComparable) element).CompareTo (minimum);
1344                                         else
1345                                                 throw new ArgumentNullException ();
1346
1347                                         if (comparison < 0)
1348                                                 minimum = element;
1349                                 }
1350                                 counter++;
1351                         }
1352
1353                         if (counter == 0)
1354                                 throw new InvalidOperationException ();
1355                         else
1356                                 return minimum;
1357                 }
1358
1359                 public static int Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1360                 {
1361                         Check.SourceAndSelector (source, selector);
1362
1363                         return Iterate (source, int.MaxValue, (a, b) => Math.Min (selector (a), b));
1364                 }
1365
1366                 public static long Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1367                 {
1368                         Check.SourceAndSelector (source, selector);
1369
1370                         return Iterate (source, long.MaxValue, (a, b) => Math.Min (selector (a), b));
1371                 }
1372
1373                 public static double Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1374                 {
1375                         Check.SourceAndSelector (source, selector);
1376
1377                         return Iterate (source, double.MaxValue, (a, b) => Math.Min (selector (a), b));
1378                 }
1379
1380                 public static float Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1381                 {
1382                         Check.SourceAndSelector (source, selector);
1383
1384                         return Iterate (source, float.MaxValue, (a, b) => Math.Min (selector (a), b));
1385                 }
1386
1387                 public static decimal Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1388                 {
1389                         Check.SourceAndSelector (source, selector);
1390
1391                         return Iterate (source, decimal.MaxValue, (a, b) => Math.Min (selector (a), b));
1392                 }
1393
1394                 public static int? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1395                 {
1396                         Check.SourceAndSelector (source, selector);
1397
1398                         return IterateNullable (source, int.MaxValue, (a, b) => {
1399                                 var v = selector (a); return v < b ? v : b;
1400                         });
1401                 }
1402
1403                 public static long? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1404                 {
1405                         Check.SourceAndSelector (source, selector);
1406
1407                         return IterateNullable (source, long.MaxValue, (a, b) => {
1408                                 var v = selector (a); return v < b ? v : b;
1409                         });
1410                 }
1411
1412                 public static float? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1413                 {
1414                         Check.SourceAndSelector (source, selector);
1415
1416                         return IterateNullable (source, float.MaxValue, (a, b) => {
1417                                 var v = selector (a); return v < b ? v : b;
1418                         });
1419                 }
1420
1421                 public static double? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1422                 {
1423                         Check.SourceAndSelector (source, selector);
1424
1425                         return IterateNullable (source, double.MaxValue, (a, b) => {
1426                                 var v = selector (a); return v < b ? v : b;
1427                         });
1428                 }
1429
1430                 public static decimal? Min<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1431                 {
1432                         Check.SourceAndSelector (source, selector);
1433
1434                         return IterateNullable (source, decimal.MaxValue, (a, b) => {
1435                                 var v = selector (a); return v < b ? v : b;
1436                         });
1437                 }
1438
1439                 public static TResult Min<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1440                 {
1441                         Check.SourceAndSelector (source, selector);
1442
1443                         bool notAssigned = true;
1444                         TResult minimum = default (TResult);
1445                         int counter = 0;
1446                         foreach (TSource item in source) {
1447                                 TResult element = selector (item);
1448                                 if (notAssigned) {
1449                                         minimum = element;
1450                                         notAssigned = false;
1451                                 } else {
1452                                         int comparison;
1453                                         if (element is IComparable<TResult>)
1454                                                 comparison = ((IComparable<TResult>) element).CompareTo (minimum);
1455                                         else if (element is System.IComparable)
1456                                                 comparison = ((System.IComparable) element).CompareTo (minimum);
1457                                         else
1458                                                 throw new ArgumentNullException ();
1459
1460                                         if (comparison < 0)
1461                                                 minimum = element;
1462                                 }
1463                                 counter++;
1464                         }
1465
1466                         if (counter == 0)
1467                                 throw new InvalidOperationException ();
1468                         else
1469                                 return minimum;
1470                 }
1471
1472                 #endregion
1473
1474                 #region OfType
1475
1476                 public static IEnumerable<TResult> OfType<TResult> (this IEnumerable source)
1477                 {
1478                         Check.Source (source);
1479
1480                         return CreateOfTypeIterator<TResult> (source);
1481                 }
1482
1483                 static IEnumerable<TResult> CreateOfTypeIterator<TResult> (IEnumerable source)
1484                 {
1485                         foreach (object element in source)
1486                                 if (element is TResult)
1487                                         yield return (TResult) element;
1488                 }
1489
1490                 #endregion
1491
1492                 #region OrderBy
1493
1494                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
1495                                 Func<TSource, TKey> keySelector)
1496                 {
1497                         return OrderBy<TSource, TKey> (source, keySelector, null);
1498                 }
1499
1500                 public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey> (this IEnumerable<TSource> source,
1501                                 Func<TSource, TKey> keySelector,
1502                                 IComparer<TKey> comparer)
1503                 {
1504                         Check.SourceAndKeySelector (source, keySelector);
1505
1506                         return new OrderedSequence<TSource, TKey> (source, keySelector, comparer, SortDirection.Ascending);
1507                 }
1508
1509                 #endregion
1510
1511                 #region OrderByDescending
1512
1513                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
1514                                 Func<TSource, TKey> keySelector)
1515                 {
1516                         return OrderByDescending<TSource, TKey> (source, keySelector, null);
1517                 }
1518
1519                 public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source,
1520                                 Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
1521                 {
1522                         Check.SourceAndKeySelector (source, keySelector);
1523
1524                         return new OrderedSequence<TSource, TKey> (source, keySelector, comparer, SortDirection.Descending);
1525                 }
1526
1527                 #endregion
1528
1529                 #region Range
1530
1531                 public static IEnumerable<int> Range (int start, int count)
1532                 {
1533                         if (count < 0)
1534                                 throw new ArgumentOutOfRangeException ("count");
1535
1536                         long upto = ((long) start + count) - 1;
1537
1538                         if (upto > int.MaxValue)
1539                                 throw new ArgumentOutOfRangeException ();
1540
1541                         return CreateRangeIterator (start, (int) upto);
1542                 }
1543
1544                 static IEnumerable<int> CreateRangeIterator (int start, int upto)
1545                 {
1546                         for (int i = start; i <= upto; i++)
1547                                 yield return i;
1548                 }
1549
1550                 #endregion
1551
1552                 #region Repeat
1553
1554                 public static IEnumerable<TResult> Repeat<TResult> (TResult element, int count)
1555                 {
1556                         if (count < 0)
1557                                 throw new ArgumentOutOfRangeException ();
1558
1559                         return CreateRepeatIterator (element, count);
1560                 }
1561
1562                 static IEnumerable<TResult> CreateRepeatIterator<TResult> (TResult element, int count)
1563                 {
1564                         for (int i = 0; i < count; i++)
1565                                 yield return element;
1566                 }
1567
1568                 #endregion
1569
1570                 #region Reverse
1571
1572                 public static IEnumerable<TSource> Reverse<TSource> (this IEnumerable<TSource> source)
1573                 {
1574                         Check.Source (source);
1575
1576                         var list = source as IList<TSource>;
1577                         if (list == null)
1578                                 list = new List<TSource> (source);
1579
1580                         return CreateReverseIterator (list);
1581                 }
1582
1583                 static IEnumerable<TSource> CreateReverseIterator<TSource> (IList<TSource> source)
1584                 {
1585                         for (int i = source.Count; i > 0; --i)
1586                                 yield return source [i - 1];
1587                 }
1588
1589                 #endregion
1590
1591                 #region Select
1592
1593                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, TResult> selector)
1594                 {
1595                         Check.SourceAndSelector (source, selector);
1596
1597                         return CreateSelectIterator (source, selector);
1598                 }
1599
1600                 static IEnumerable<TResult> CreateSelectIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, TResult> selector)
1601                 {
1602                         foreach (var element in source)
1603                                 yield return selector (element);
1604                 }
1605
1606                 public static IEnumerable<TResult> Select<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, int, 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, int, TResult> selector)
1614                 {
1615                         int counter = 0;
1616                         foreach (TSource element in source) {
1617                                 yield return selector (element, counter);
1618                                 counter++;
1619                         }
1620                 }
1621
1622                 #endregion
1623
1624                 #region SelectMany
1625
1626                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
1627                 {
1628                         Check.SourceAndSelector (source, selector);
1629
1630                         return CreateSelectManyIterator (source, selector);
1631                 }
1632
1633                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
1634                 {
1635                         foreach (TSource element in source)
1636                                 foreach (TResult item in selector (element))
1637                                         yield return item;
1638                 }
1639
1640                 public static IEnumerable<TResult> SelectMany<TSource, TResult> (this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
1641                 {
1642                         Check.SourceAndSelector (source, selector);
1643
1644                         return CreateSelectManyIterator (source, selector);
1645                 }
1646
1647                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TResult> (IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector)
1648                 {
1649                         int counter = 0;
1650                         foreach (TSource element in source) {
1651                                 foreach (TResult item in selector (element, counter))
1652                                         yield return item;
1653                                 counter++;
1654                         }
1655                 }
1656
1657                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
1658                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1659                 {
1660                         Check.SourceAndCollectionSelectors (source, collectionSelector, selector);
1661
1662                         return CreateSelectManyIterator (source, collectionSelector, selector);
1663                 }
1664
1665                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult> (IEnumerable<TSource> source,
1666                         Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1667                 {
1668                         foreach (TSource element in source)
1669                                 foreach (TCollection collection in collectionSelector (element))
1670                                         yield return selector (element, collection);
1671                 }
1672
1673                 public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult> (this IEnumerable<TSource> source,
1674                         Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1675                 {
1676                         Check.SourceAndCollectionSelectors (source, collectionSelector, selector);
1677
1678                         return CreateSelectManyIterator (source, collectionSelector, selector);
1679                 }
1680
1681                 static IEnumerable<TResult> CreateSelectManyIterator<TSource, TCollection, TResult> (IEnumerable<TSource> source,
1682                         Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> selector)
1683                 {
1684                         int counter = 0;
1685                         foreach (TSource element in source)
1686                                 foreach (TCollection collection in collectionSelector (element, counter++))
1687                                         yield return selector (element, collection);
1688                 }
1689
1690                 #endregion
1691
1692                 #region Single
1693
1694                 static TSource Single<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate, Fallback fallback)
1695                 {
1696                         var found = false;
1697                         var item = default (TSource);
1698
1699                         foreach (var element in source) {
1700                                 if (!predicate (element))
1701                                         continue;
1702
1703                                 if (found)
1704                                         throw new InvalidOperationException ();
1705
1706                                 found = true;
1707                                 item = element;
1708                         }
1709
1710                         if (!found && fallback == Fallback.Throw)
1711                                 throw new InvalidOperationException ();
1712
1713                         return item;
1714                 }
1715
1716                 public static TSource Single<TSource> (this IEnumerable<TSource> source)
1717                 {
1718                         Check.Source (source);
1719
1720                         return source.Single (PredicateOf<TSource>.Always, Fallback.Throw);
1721                 }
1722
1723                 public static TSource Single<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1724                 {
1725                         Check.SourceAndPredicate (source, predicate);
1726
1727                         return source.Single (predicate, Fallback.Throw);
1728                 }
1729
1730                 #endregion
1731
1732                 #region SingleOrDefault
1733
1734                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source)
1735                 {
1736                         Check.Source (source);
1737
1738                         return source.Single (PredicateOf<TSource>.Always, Fallback.Default);
1739                 }
1740
1741                 public static TSource SingleOrDefault<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1742                 {
1743                         Check.SourceAndPredicate (source, predicate);
1744
1745                         return source.Single (predicate, Fallback.Default);
1746                 }
1747
1748                 #endregion
1749
1750                 #region Skip
1751
1752                 public static IEnumerable<TSource> Skip<TSource> (this IEnumerable<TSource> source, int count)
1753                 {
1754                         Check.Source (source);
1755
1756                         return CreateSkipIterator (source, count);
1757                 }
1758
1759                 static IEnumerable<TSource> CreateSkipIterator<TSource> (IEnumerable<TSource> source, int count)
1760                 {
1761                         int i = 0;
1762                         foreach (var element in source) {
1763                                 if (i++ < count)
1764                                         continue;
1765
1766                                 yield return element;
1767                         }
1768                 }
1769
1770                 #endregion
1771
1772                 #region SkipWhile
1773
1774                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
1775                 {
1776                         Check.SourceAndPredicate (source, predicate);
1777
1778                         return CreateSkipWhileIterator (source, predicate);
1779                 }
1780
1781                 static IEnumerable<TSource> CreateSkipWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
1782                 {
1783                         bool yield = false;
1784
1785                         foreach (TSource element in source) {
1786                                 if (yield)
1787                                         yield return element;
1788                                 else
1789                                         if (!predicate (element)) {
1790                                                 yield return element;
1791                                                 yield = true;
1792                                         }
1793                         }
1794                 }
1795
1796                 public static IEnumerable<TSource> SkipWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
1797                 {
1798                         Check.SourceAndPredicate (source, predicate);
1799
1800                         return CreateSkipWhileIterator (source, predicate);
1801                 }
1802
1803                 static IEnumerable<TSource> CreateSkipWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
1804                 {
1805                         int counter = 0;
1806                         bool yield = false;
1807
1808                         foreach (TSource element in source) {
1809                                 if (yield)
1810                                         yield return element;
1811                                 else
1812                                         if (!predicate (element, counter)) {
1813                                                 yield return element;
1814                                                 yield = true;
1815                                         }
1816                                 counter++;
1817                         }
1818                 }
1819
1820                 #endregion
1821
1822                 #region Sum
1823
1824                 public static int Sum (this IEnumerable<int> source)
1825                 {
1826                         Check.Source (source);
1827
1828                         return Sum<int, int> (source, (a, b) => a + b);
1829                 }
1830
1831                 public static int? Sum (this IEnumerable<int?> source)
1832                 {
1833                         Check.Source (source);
1834
1835                         return source.SumNullable<int?, int?> (0, (a, b) => a.HasValue ? a + b : a);
1836                 }
1837
1838                 public static int Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int> selector)
1839                 {
1840                         Check.SourceAndSelector (source, selector);
1841
1842                         return Sum<TSource, int> (source, (a, b) => a + selector (b));
1843                 }
1844
1845                 public static int? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, int?> selector)
1846                 {
1847                         Check.SourceAndSelector (source, selector);
1848
1849                         return source.SumNullable<TSource, int?> (0, (a, b) => {
1850                                 var value = selector (b);
1851                                 return value.HasValue ? a + value.Value : a;
1852                         });
1853                 }
1854
1855                 public static long Sum (this IEnumerable<long> source)
1856                 {
1857                         Check.Source (source);
1858
1859                         return Sum<long, long> (source, (a, b) => a + b);
1860                 }
1861
1862                 public static long? Sum (this IEnumerable<long?> source)
1863                 {
1864                         Check.Source (source);
1865
1866                         return source.SumNullable<long?, long?> (0, (a, b) => a.HasValue ? a + b : a);
1867                 }
1868
1869                 public static long Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long> selector)
1870                 {
1871                         Check.SourceAndSelector (source, selector);
1872
1873                         return Sum<TSource, long> (source, (a, b) => a + selector (b));
1874                 }
1875
1876                 public static long? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, long?> selector)
1877                 {
1878                         Check.SourceAndSelector (source, selector);
1879
1880                         return source.SumNullable<TSource, long?> (0, (a, b) => {
1881                                 var value = selector (b);
1882                                 return value.HasValue ? a + value.Value : a;
1883                         });
1884                 }
1885
1886                 public static double Sum (this IEnumerable<double> source)
1887                 {
1888                         Check.Source (source);
1889
1890                         return Sum<double, double> (source, (a, b) => a + b);
1891                 }
1892
1893                 public static double? Sum (this IEnumerable<double?> source)
1894                 {
1895                         Check.Source (source);
1896
1897                         return source.SumNullable<double?, double?> (0, (a, b) => a.HasValue ? a + b : a);
1898                 }
1899
1900                 public static double Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double> selector)
1901                 {
1902                         Check.SourceAndSelector (source, selector);
1903
1904                         return Sum<TSource, double> (source, (a, b) => a + selector (b));
1905                 }
1906
1907                 public static double? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, double?> selector)
1908                 {
1909                         Check.SourceAndSelector (source, selector);
1910
1911                         return source.SumNullable<TSource, double?> (0, (a, b) => {
1912                                 var value = selector (b);
1913                                 return value.HasValue ? a + value.Value : a;
1914                         });
1915                 }
1916
1917                 public static float Sum (this IEnumerable<float> source)
1918                 {
1919                         Check.Source (source);
1920
1921                         return Sum<float, float> (source, (a, b) => a + b);
1922                 }
1923
1924                 public static float? Sum (this IEnumerable<float?> source)
1925                 {
1926                         Check.Source (source);
1927
1928                         return source.SumNullable<float?, float?> (0, (a, b) => a.HasValue ? a + b : a);
1929                 }
1930
1931                 public static float Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float> selector)
1932                 {
1933                         Check.SourceAndSelector (source, selector);
1934
1935                         return Sum<TSource, float> (source, (a, b) => a + selector (b));
1936                 }
1937
1938                 public static float? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, float?> selector)
1939                 {
1940                         Check.SourceAndSelector (source, selector);
1941
1942                         return source.SumNullable<TSource, float?> (0, (a, b) => {
1943                                 var value = selector (b);
1944                                 return value.HasValue ? a + value.Value : a;
1945                         });
1946                 }
1947
1948                 public static decimal Sum (this IEnumerable<decimal> source)
1949                 {
1950                         Check.Source (source);
1951
1952                         return Sum<decimal, decimal> (source, (a, b) => a + b);
1953                 }
1954
1955                 public static decimal? Sum (this IEnumerable<decimal?> source)
1956                 {
1957                         Check.Source (source);
1958
1959                         return source.SumNullable<decimal?, decimal?> (0, (a, b) => a.HasValue ? a + b : a);
1960                 }
1961
1962                 public static decimal Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal> selector)
1963                 {
1964                         Check.SourceAndSelector (source, selector);
1965
1966                         return Sum<TSource, decimal> (source, (a, b) => a + selector (b));
1967                 }
1968
1969                 public static decimal? Sum<TSource> (this IEnumerable<TSource> source, Func<TSource, decimal?> selector)
1970                 {
1971                         Check.SourceAndSelector (source, selector);
1972
1973                         return source.SumNullable<TSource, decimal?> (0, (a, b) => {
1974                                 var value = selector (b);
1975                                 return value.HasValue ? a + value.Value : a;
1976                         });
1977                 }
1978
1979                 static TR Sum<TA, TR> (this IEnumerable<TA> source, Func<TR, TA, TR> selector)
1980                 {
1981                         TR total = default (TR);
1982                         long counter = 0;
1983                         foreach (var element in source) {
1984                                 total = selector (total, element);
1985                                 ++counter;
1986                         }
1987
1988                         return total;
1989                 }
1990
1991                 static TR SumNullable<TA, TR> (this IEnumerable<TA> source, TR zero, Func<TR, TA, TR> selector)
1992                 {
1993                         TR total = zero;
1994                         foreach (var element in source) {
1995                                 total = selector (total, element);
1996                         }
1997
1998                         return total;
1999                 }
2000
2001                 #endregion
2002
2003                 #region Take
2004
2005                 public static IEnumerable<TSource> Take<TSource> (this IEnumerable<TSource> source, int count)
2006                 {
2007                         Check.Source (source);
2008
2009                         return CreateTakeIterator (source, count);
2010                 }
2011
2012                 static IEnumerable<TSource> CreateTakeIterator<TSource> (IEnumerable<TSource> source, int count)
2013                 {
2014                         if (count <= 0)
2015                                 yield break;
2016
2017                         int counter = 0;
2018                         foreach (TSource element in source) {
2019                                 if (counter++ == count)
2020                                         yield break;
2021
2022                                 yield return element;
2023                         }
2024                 }
2025
2026                 #endregion
2027
2028                 #region TakeWhile
2029
2030                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2031                 {
2032                         Check.SourceAndPredicate (source, predicate);
2033
2034                         return CreateTakeWhileIterator (source, predicate);
2035                 }
2036
2037                 static IEnumerable<TSource> CreateTakeWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
2038                 {
2039                         foreach (var element in source) {
2040                                 if (!predicate (element))
2041                                         yield break;
2042
2043                                 yield return element;
2044                         }
2045                 }
2046
2047                 public static IEnumerable<TSource> TakeWhile<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2048                 {
2049                         Check.SourceAndPredicate (source, predicate);
2050
2051                         return CreateTakeWhileIterator (source, predicate);
2052                 }
2053
2054                 static IEnumerable<TSource> CreateTakeWhileIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2055                 {
2056                         int counter = 0;
2057                         foreach (var element in source) {
2058                                 if (!predicate (element, counter))
2059                                         yield break;
2060
2061                                 yield return element;
2062                                 counter++;
2063                         }
2064                 }
2065
2066                 #endregion
2067
2068                 #region ThenBy
2069
2070                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2071                 {
2072                         return ThenBy<TSource, TKey> (source, keySelector, null);
2073                 }
2074
2075                 public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2076                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2077                 {
2078                         Check.SourceAndKeySelector (source, keySelector);
2079
2080                         return source.CreateOrderedEnumerable (keySelector, comparer, false);
2081                 }
2082
2083                 #endregion
2084
2085                 #region ThenByDescending
2086
2087                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2088                         Func<TSource, TKey> keySelector)
2089                 {
2090                         return ThenByDescending<TSource, TKey> (source, keySelector, null);
2091                 }
2092
2093                 public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey> (this IOrderedEnumerable<TSource> source,
2094                         Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
2095                 {
2096                         Check.SourceAndKeySelector (source, keySelector);
2097
2098                         return source.CreateOrderedEnumerable (keySelector, comparer, true);
2099                 }
2100
2101                 #endregion
2102
2103                 #region ToArray
2104
2105                 public static TSource [] ToArray<TSource> (this IEnumerable<TSource> source)
2106                 {
2107                         Check.Source (source);
2108
2109                         var collection = source as ICollection<TSource>;
2110                         if (collection != null) {
2111                                 var array = new TSource [collection.Count];
2112                                 collection.CopyTo (array, 0);
2113                                 return array;
2114                         }
2115
2116                         return new List<TSource> (source).ToArray ();
2117                 }
2118
2119                 #endregion
2120
2121                 #region ToDictionary
2122                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2123                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2124                 {
2125                         return ToDictionary<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2126                 }
2127
2128                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2129                                 Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2130                 {
2131                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2132
2133                         if (comparer == null)
2134                                 comparer = EqualityComparer<TKey>.Default;
2135
2136                         var dict = new Dictionary<TKey, TElement> (comparer);
2137                         foreach (var e in source)
2138                                 dict.Add (keySelector (e), elementSelector (e));
2139
2140                         return dict;
2141                 }
2142
2143                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2144                                 Func<TSource, TKey> keySelector)
2145                 {
2146                         return ToDictionary (source, keySelector, null);
2147                 }
2148
2149                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this IEnumerable<TSource> source,
2150                                 Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2151                 {
2152                         Check.SourceAndKeySelector (source, keySelector);
2153
2154                         if (comparer == null)
2155                                 comparer = EqualityComparer<TKey>.Default;
2156
2157                         var dict = new Dictionary<TKey, TSource> (comparer);
2158                         foreach (var e in source)
2159                                 dict.Add (keySelector (e), e);
2160
2161                         return dict;
2162                 }
2163
2164                 #endregion
2165
2166                 #region ToList
2167                 public static List<TSource> ToList<TSource> (this IEnumerable<TSource> source)
2168                 {
2169                         Check.Source (source);
2170
2171                         return new List<TSource> (source);
2172                 }
2173                 #endregion
2174
2175                 #region ToLookup
2176
2177                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
2178                 {
2179                         return ToLookup<TSource, TKey> (source, keySelector, null);
2180                 }
2181
2182                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this IEnumerable<TSource> source,
2183                         Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
2184                 {
2185                         Check.SourceAndKeySelector (source, keySelector);
2186
2187                         var dictionary = new Dictionary<TKey, List<TSource>> (comparer ?? EqualityComparer<TKey>.Default);
2188                         foreach (TSource element in source) {
2189                                 TKey key = keySelector (element);
2190                                 if (key == null)
2191                                         throw new ArgumentNullException ();
2192                                 if (!dictionary.ContainsKey (key))
2193                                         dictionary.Add (key, new List<TSource> ());
2194                                 dictionary [key].Add (element);
2195                         }
2196                         return new Lookup<TKey, TSource> (dictionary);
2197                 }
2198
2199                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2200                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
2201                 {
2202                         return ToLookup<TSource, TKey, TElement> (source, keySelector, elementSelector, null);
2203                 }
2204
2205                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this IEnumerable<TSource> source,
2206                         Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
2207                 {
2208                         Check.SourceAndKeyElementSelectors (source, keySelector, elementSelector);
2209
2210                         Dictionary<TKey, List<TElement>> dictionary = new Dictionary<TKey, List<TElement>> (comparer ?? EqualityComparer<TKey>.Default);
2211                         foreach (TSource element in source) {
2212                                 TKey key = keySelector (element);
2213                                 if (key == null)
2214                                         throw new ArgumentNullException ();
2215                                 if (!dictionary.ContainsKey (key))
2216                                         dictionary.Add (key, new List<TElement> ());
2217                                 dictionary [key].Add (elementSelector (element));
2218                         }
2219                         return new Lookup<TKey, TElement> (dictionary);
2220                 }
2221
2222                 #endregion
2223
2224                 #region SequenceEqual
2225
2226                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2227                 {
2228                         return first.SequenceEqual (second, null);
2229                 }
2230
2231                 public static bool SequenceEqual<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2232                 {
2233                         Check.FirstAndSecond (first, second);
2234
2235                         if (comparer == null)
2236                                 comparer = EqualityComparer<TSource>.Default;
2237
2238                         var first_enumerator = first.GetEnumerator ();
2239                         var second_enumerator = second.GetEnumerator ();
2240
2241                         while (first_enumerator.MoveNext ()) {
2242                                 if (!second_enumerator.MoveNext ())
2243                                         return false;
2244
2245                                 if (!comparer.Equals (first_enumerator.Current, second_enumerator.Current))
2246                                         return false;
2247                         }
2248
2249                         return !second_enumerator.MoveNext ();
2250                 }
2251
2252                 #endregion
2253
2254                 #region Union
2255
2256                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
2257                 {
2258                         Check.FirstAndSecond (first, second);
2259
2260                         return first.Union (second, null);
2261                 }
2262
2263                 public static IEnumerable<TSource> Union<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2264                 {
2265                         Check.FirstAndSecond (first, second);
2266
2267                         if (comparer == null)
2268                                 comparer = EqualityComparer<TSource>.Default;
2269
2270                         return CreateUnionIterator (first, second, comparer);
2271                 }
2272
2273                 static IEnumerable<TSource> CreateUnionIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
2274                 {
2275                         var items = new HashSet<TSource> (comparer);
2276                         foreach (var element in first) {
2277                                 if (! items.Contains (element)) {
2278                                         items.Add (element);
2279                                         yield return element;
2280                                 }
2281                         }
2282
2283                         foreach (var element in second) {
2284                                 if (! items.Contains (element, comparer)) {
2285                                         items.Add (element);
2286                                         yield return element;
2287                                 }
2288                         }
2289                 }
2290
2291                 #endregion
2292
2293                 #region Where
2294
2295                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
2296                 {
2297                         Check.SourceAndPredicate (source, predicate);
2298
2299                         return CreateWhereIterator (source, predicate);
2300                 }
2301
2302                 static IEnumerable<TSource> CreateWhereIterator<TSource> (IEnumerable<TSource> source, Func<TSource, bool> predicate)
2303                 {
2304                         foreach (TSource element in source)
2305                                 if (predicate (element))
2306                                         yield return element;
2307                 }
2308
2309                 public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2310                 {
2311                         Check.SourceAndPredicate (source, predicate);
2312
2313                         return CreateWhereIterator (source, predicate);
2314                 }
2315
2316                 static IEnumerable<TSource> CreateWhereIterator<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
2317                 {
2318                         int counter = 0;
2319                         foreach (TSource element in source) {
2320                                 if (predicate (element, counter))
2321                                         yield return element;
2322                                 counter++;
2323                         }
2324                 }
2325
2326                 #endregion
2327
2328                 class ReadOnlyCollectionOf<T> {
2329                         public static readonly ReadOnlyCollection<T> Empty = new ReadOnlyCollection<T> (new T [0]);
2330                 }
2331
2332                 internal static ReadOnlyCollection<TSource> ToReadOnlyCollection<TSource> (this IEnumerable<TSource> source)
2333                 {
2334                         if (source == null)
2335                                 return ReadOnlyCollectionOf<TSource>.Empty;
2336
2337                         var ro = source as ReadOnlyCollection<TSource>;
2338                         if (ro != null)
2339                                 return ro;
2340
2341                         return new ReadOnlyCollection<TSource> (source.ToArray<TSource> ());
2342                 }
2343         }
2344 }