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