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