Merge pull request #829 from symform/httpwebreq-async-ssl
[mono.git] / mcs / class / System.Core / System.Linq / Enumerable.cs
index e302a7add3a42e5d8e9d68bd7904734d30bb1114..23805636c6b6236d00dc7b20fce0feeb83ffd659 100644 (file)
@@ -73,7 +73,7 @@ namespace System.Linq
                        // if zero elements and treat the first element differently
                        using (var enumerator = source.GetEnumerator ()) {
                                if (!enumerator.MoveNext ())
-                                       throw new InvalidOperationException ("No elements in source list");
+                                       throw EmptySequence ();
 
                                TSource folded = enumerator.Current;
                                while (enumerator.MoveNext ())
@@ -173,7 +173,7 @@ namespace System.Linq
                                count++;
                        }
                        if (count == 0)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return total / (double) count;
                }
 
@@ -188,7 +188,7 @@ namespace System.Linq
                                count++;
                        }
                        if (count == 0)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return total / (double) count;
                }
 
@@ -203,7 +203,7 @@ namespace System.Linq
                                count++;
                        }
                        if (count == 0)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return total / count;
                }
 
@@ -218,7 +218,7 @@ namespace System.Linq
                                count++;
                        }
                        if (count == 0)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return total / count;
                }
 
@@ -233,7 +233,7 @@ namespace System.Linq
                                count++;
                        }
                        if (count == 0)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return total / count;
                }
 
@@ -381,7 +381,7 @@ namespace System.Linq
                                count++;
                        }
                        if (count == 0)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw EmptySequence ();
                        return total / (double) count;
                }
 
@@ -418,7 +418,7 @@ namespace System.Linq
                                count++;
                        }
                        if (count == 0)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw EmptySequence ();
                        return total / (double) count;
 
                }
@@ -456,7 +456,7 @@ namespace System.Linq
                                count++;
                        }
                        if (count == 0)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw EmptySequence ();
                        return total / count;
 
                }
@@ -495,7 +495,7 @@ namespace System.Linq
                                count++;
                        }
                        if (count == 0)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw EmptySequence ();
                        return total / count;
                }
 
@@ -532,7 +532,7 @@ namespace System.Linq
                                count++;
                        }
                        if (count == 0)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw EmptySequence ();
                        return total / count;
                }
 
@@ -744,6 +744,12 @@ namespace System.Linq
                        if (list != null)
                                return list [index];
 
+#if NET_4_5
+                       var readOnlyList = source as IReadOnlyList<TSource>;
+                       if (readOnlyList != null)
+                               return readOnlyList[index];
+#endif
+
                        return source.ElementAt (index, Fallback.Throw);
                }
 
@@ -762,6 +768,12 @@ namespace System.Linq
                        if (list != null)
                                return index < list.Count ? list [index] : default (TSource);
 
+#if NET_4_5
+                       var readOnlyList = source as IReadOnlyList<TSource>;
+                       if (readOnlyList != null)
+                               return index < readOnlyList.Count ? readOnlyList [index] : default (TSource);
+#endif
+
                        return source.ElementAt (index, Fallback.Default);
                }
 
@@ -813,7 +825,7 @@ namespace System.Linq
                                        return element;
 
                        if (fallback == Fallback.Throw)
-                               throw new InvalidOperationException (Locale.GetText ("Sequence contains no matching element"));
+                               throw NoMatchingElement ();
 
                        return default (TSource);
                }
@@ -833,7 +845,7 @@ namespace System.Linq
                                }
                        }
 
-                       throw new InvalidOperationException ("The source sequence is empty");
+                       throw EmptySequence ();
                }
 
                public static TSource First<TSource> (this IEnumerable<TSource> source, Func<TSource, bool> predicate)
@@ -1099,7 +1111,7 @@ namespace System.Linq
 
                        foreach (TOuter element in outer) {
                                TKey outerKey = outerKeySelector (element);
-                               if (innerKeys.Contains (outerKey))
+                               if (outerKey != null && innerKeys.Contains (outerKey))
                                        yield return resultSelector (element, innerKeys [outerKey]);
                                else
                                        yield return resultSelector (element, Empty<TInner> ());
@@ -1166,7 +1178,7 @@ namespace System.Linq
 
                        foreach (TOuter element in outer) {
                                TKey outerKey = outerKeySelector (element);
-                               if (innerKeys.Contains (outerKey)) {
+                               if (outerKey != null && innerKeys.Contains (outerKey)) {
                                        foreach (TInner innerElement in innerKeys [outerKey])
                                                yield return resultSelector (element, innerElement);
                                }
@@ -1201,7 +1213,7 @@ namespace System.Linq
                                return item;
 
                        if (fallback == Fallback.Throw)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw NoMatchingElement ();
 
                        return item;
                }
@@ -1212,7 +1224,7 @@ namespace System.Linq
 
                        var collection = source as ICollection<TSource>;
                        if (collection != null && collection.Count == 0)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
 
                        var list = source as IList<TSource>;
                        if (list != null)
@@ -1232,7 +1244,7 @@ namespace System.Linq
                        if (!empty)
                                return item;
 
-                       throw new InvalidOperationException (Locale.GetText ("Sequence contains no elements"));
+                       throw EmptySequence ();
 #endif
         }
 
@@ -1329,7 +1341,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                               throw new InvalidOperationException (Locale.GetText ("Sequence contains no elements"));
+                               throw EmptySequence();
                        return max;
                }
 
@@ -1344,7 +1356,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return max;
                }
 
@@ -1359,7 +1371,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return max;
                }
 
@@ -1374,7 +1386,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return max;
                }
 
@@ -1389,7 +1401,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return max;
                }
 
@@ -1527,7 +1539,7 @@ namespace System.Linq
                                                max = element;
                                }
                                if (empty)
-                    throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                                       throw EmptySequence ();
                        }
                        return max;
                }
@@ -1543,7 +1555,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw NoMatchingElement ();
                        return max;
                }
 
@@ -1558,7 +1570,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw NoMatchingElement ();
                        return max;
                }
 
@@ -1573,7 +1585,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw NoMatchingElement ();
                        return max;
                }
 
@@ -1588,7 +1600,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw NoMatchingElement ();
                        return max;
                }
 
@@ -1603,7 +1615,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw NoMatchingElement ();
                        return max;
                }
 
@@ -1616,7 +1628,7 @@ namespace System.Linq
                        }
 
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw NoMatchingElement ();
 
                        return initValue;
                }
@@ -1749,7 +1761,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return min;
                }
 
@@ -1764,7 +1776,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return min;
                }
 
@@ -1779,7 +1791,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return min;
                }
 
@@ -1794,7 +1806,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return min;
                }
 
@@ -1809,7 +1821,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                               throw EmptySequence ();
                        return min;
                }
 
@@ -1946,7 +1958,7 @@ namespace System.Linq
                                                min = element;
                                }
                                if (empty)
-                    throw new InvalidOperationException(Locale.GetText("Sequence contains no elements"));
+                                       throw EmptySequence ();
                        }
                        return min;
                }
@@ -1962,7 +1974,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw NoMatchingElement ();
                        return min;
                }
 
@@ -1977,7 +1989,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw NoMatchingElement ();
                        return min;
                }
 
@@ -1992,7 +2004,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                               throw new InvalidOperationException (Locale.GetText("Sequence contains no matching elements");
+                               throw NoMatchingElement ();
                        return min;
                }
 
@@ -2007,7 +2019,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw NoMatchingElement ();
                        return min;
                }
 
@@ -2022,7 +2034,7 @@ namespace System.Linq
                                empty = false;
                        }
                        if (empty)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw NoMatchingElement ();
                        return min;
                }
 
@@ -2367,14 +2379,14 @@ namespace System.Linq
                                        continue;
 
                                if (found)
-                                       throw new InvalidOperationException (Locale.GetText ("Sequence contains more than one element"));
+                                       throw MoreThanOneMatchingElement ();
 
                                found = true;
                                item = element;
                        }
 
                        if (!found && fallback == Fallback.Throw)
-                throw new InvalidOperationException(Locale.GetText("Sequence contains no matching elements"));
+                               throw NoMatchingElement ();
 
                        return item;
                }
@@ -2391,14 +2403,14 @@ namespace System.Linq
 
                        foreach (var element in source) {
                                if (found)
-                                       throw new InvalidOperationException (Locale.GetText ("Sequence contains more than one element"));
+                                       throw MoreThanOneElement ();
 
                                found = true;
                                item = element;
                        }
 
                        if (!found)
-                               throw new InvalidOperationException (Locale.GetText ("Sequence contains no matching elements"));
+                               throw NoMatchingElement ();
 
                        return item;
 #endif
@@ -2427,7 +2439,7 @@ namespace System.Linq
 
                        foreach (var element in source) {
                                if (found)
-                                       throw new InvalidOperationException (Locale.GetText ("Sequence contains more than one element"));
+                                       throw MoreThanOneMatchingElement ();
 
                                found = true;
                                item = element;
@@ -2885,7 +2897,7 @@ namespace System.Linq
                                collection.CopyTo (array, 0);
                                return array;
                        }
-                       
+
                        int pos = 0;
                        array = EmptyOf<TSource>.Instance;
                        foreach (var element in source) {
@@ -3072,7 +3084,7 @@ namespace System.Linq
 
                #endregion
                
-#if NET_4_0 || MOONLIGHT || MOBILE
+#if NET_4_0
                #region Zip
                
                public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult> (this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
@@ -3105,6 +3117,11 @@ namespace System.Linq
                {
                        Check.SourceAndPredicate (source, predicate);
 
+                       // It cannot be IList<TSource> because it may break on user implementation
+                       var array = source as TSource[];
+                       if (array != null)
+                               return CreateWhereIterator (array, predicate);
+
                        return CreateWhereIterator (source, predicate);
                }
 
@@ -3115,14 +3132,27 @@ namespace System.Linq
                                        yield return element;
                }
 
+               static IEnumerable<TSource> CreateWhereIterator<TSource> (TSource[] source, Func<TSource, bool> predicate)
+               {
+                       for (int i = 0; i < source.Length; ++i) {
+                               var element = source [i];
+                               if (predicate (element))
+                                       yield return element;
+                       }
+               }       
+
                public static IEnumerable<TSource> Where<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
                {
                        Check.SourceAndPredicate (source, predicate);
 
+                       var array = source as TSource[];
+                       if (array != null)
+                               return CreateWhereIterator (array, predicate);
+
                        return CreateWhereIterator (source, predicate);
                }
 
-               static IEnumerable<TSource> CreateWhereIterator<TSource> (this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
+               static IEnumerable<TSource> CreateWhereIterator<TSource> (IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
                {
                        int counter = 0;
                        foreach (TSource element in source) {
@@ -3132,6 +3162,15 @@ namespace System.Linq
                        }
                }
 
+               static IEnumerable<TSource> CreateWhereIterator<TSource> (TSource[] source, Func<TSource, int, bool> predicate)
+               {
+                       for (int i = 0; i < source.Length; ++i) {
+                               var element = source [i];
+                               if (predicate (element, i))
+                                       yield return element;
+                       }
+               }
+
                #endregion
 
                internal static ReadOnlyCollection<TSource> ToReadOnlyCollection<TSource> (this IEnumerable<TSource> source)
@@ -3145,5 +3184,26 @@ namespace System.Linq
 
                        return new ReadOnlyCollection<TSource> (source.ToArray<TSource> ());
                }
+
+               #region Exception helpers
+
+               static Exception EmptySequence ()
+               {
+                       return new InvalidOperationException (Locale.GetText ("Sequence contains no elements"));
+               }
+               static Exception NoMatchingElement ()
+               {
+                       return new InvalidOperationException (Locale.GetText ("Sequence contains no matching element"));
+               }
+               static Exception MoreThanOneElement ()
+               {
+                       return new InvalidOperationException (Locale.GetText ("Sequence contains more than one element"));
+               }
+               static Exception MoreThanOneMatchingElement ()
+               {
+                       return new InvalidOperationException (Locale.GetText ("Sequence contains more than one matching element"));
+               }
+
+               #endregion
        }
 }