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