Ver Fonte

Split out into multiple files per type

Oren Novotny há 9 anos atrás
pai
commit
ffe6e1e0bf
100 ficheiros alterados com 10021 adições e 8823 exclusões
  1. 115 0
      Ix.NET/Source/System.Interactive.Async/Aggregate.cs
  2. 100 0
      Ix.NET/Source/System.Interactive.Async/AnyAll.cs
  3. 0 1739
      Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Aggregates.cs
  4. 0 295
      Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Conversions.cs
  5. 0 303
      Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Creation.cs
  6. 0 279
      Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Exceptions.cs
  7. 0 1252
      Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Generated.cs
  8. 0 648
      Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Multiple.cs
  9. 0 1882
      Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Single.cs
  10. 81 0
      Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.cs
  11. 675 0
      Ix.NET/Source/System.Interactive.Async/Average.cs
  12. 101 0
      Ix.NET/Source/System.Interactive.Async/Buffer.cs
  13. 31 0
      Ix.NET/Source/System.Interactive.Async/Cast.cs
  14. 153 0
      Ix.NET/Source/System.Interactive.Async/Catch.cs
  15. 130 0
      Ix.NET/Source/System.Interactive.Async/Concatenate.cs
  16. 51 0
      Ix.NET/Source/System.Interactive.Async/Contains.cs
  17. 89 0
      Ix.NET/Source/System.Interactive.Async/Count.cs
  18. 136 0
      Ix.NET/Source/System.Interactive.Async/Create.cs
  19. 68 0
      Ix.NET/Source/System.Interactive.Async/DefaultIfEmpty.cs
  20. 23 0
      Ix.NET/Source/System.Interactive.Async/Defer.cs
  21. 156 0
      Ix.NET/Source/System.Interactive.Async/Distinct.cs
  22. 122 0
      Ix.NET/Source/System.Interactive.Async/Do.cs
  23. 96 0
      Ix.NET/Source/System.Interactive.Async/ElementAt.cs
  24. 69 0
      Ix.NET/Source/System.Interactive.Async/Except.cs
  25. 76 0
      Ix.NET/Source/System.Interactive.Async/Expand.cs
  26. 38 0
      Ix.NET/Source/System.Interactive.Async/Finally.cs
  27. 115 0
      Ix.NET/Source/System.Interactive.Async/First.cs
  28. 113 0
      Ix.NET/Source/System.Interactive.Async/ForEach.cs
  29. 62 0
      Ix.NET/Source/System.Interactive.Async/Generate.cs
  30. 180 0
      Ix.NET/Source/System.Interactive.Async/GroupJoin.cs
  31. 348 24
      Ix.NET/Source/System.Interactive.Async/Grouping.cs
  32. 49 0
      Ix.NET/Source/System.Interactive.Async/IgnoreElements.cs
  33. 77 0
      Ix.NET/Source/System.Interactive.Async/Intersect.cs
  34. 175 0
      Ix.NET/Source/System.Interactive.Async/Join.cs
  35. 125 0
      Ix.NET/Source/System.Interactive.Async/Last.cs
  36. 229 123
      Ix.NET/Source/System.Interactive.Async/Lookup.cs
  37. 508 0
      Ix.NET/Source/System.Interactive.Async/Max.cs
  38. 549 0
      Ix.NET/Source/System.Interactive.Async/Min.cs
  39. 97 0
      Ix.NET/Source/System.Interactive.Async/OnErrorResumeNext.cs
  40. 218 0
      Ix.NET/Source/System.Interactive.Async/OrderBy.cs
  41. 23 0
      Ix.NET/Source/System.Interactive.Async/Range.cs
  42. 133 0
      Ix.NET/Source/System.Interactive.Async/Repeat.cs
  43. 48 0
      Ix.NET/Source/System.Interactive.Async/Retry.cs
  44. 51 0
      Ix.NET/Source/System.Interactive.Async/Reverse.cs
  45. 109 0
      Ix.NET/Source/System.Interactive.Async/Scan.cs
  46. 81 0
      Ix.NET/Source/System.Interactive.Async/Select.cs
  47. 164 0
      Ix.NET/Source/System.Interactive.Async/SelectMany.cs
  48. 81 0
      Ix.NET/Source/System.Interactive.Async/SequenceEqual.cs
  49. 11 0
      Ix.NET/Source/System.Interactive.Async/Set.cs
  50. 129 0
      Ix.NET/Source/System.Interactive.Async/Single.cs
  51. 192 0
      Ix.NET/Source/System.Interactive.Async/Skip.cs
  52. 23 0
      Ix.NET/Source/System.Interactive.Async/StartsWith.cs
  53. 387 0
      Ix.NET/Source/System.Interactive.Async/Sum.cs
  54. 176 0
      Ix.NET/Source/System.Interactive.Async/Take.cs
  55. 92 0
      Ix.NET/Source/System.Interactive.Async/ToAsyncEnumerable.cs
  56. 155 0
      Ix.NET/Source/System.Interactive.Async/ToCollection.cs
  57. 220 0
      Ix.NET/Source/System.Interactive.Async/ToObservable.cs
  58. 37 0
      Ix.NET/Source/System.Interactive.Async/Union.cs
  59. 71 0
      Ix.NET/Source/System.Interactive.Async/Using.cs
  60. 90 0
      Ix.NET/Source/System.Interactive.Async/Where.cs
  61. 47 0
      Ix.NET/Source/System.Interactive.Async/Zip.cs
  62. 83 0
      Ix.NET/Source/System.Interactive/Buffer.cs
  63. 63 0
      Ix.NET/Source/System.Interactive/Case.cs
  64. 153 0
      Ix.NET/Source/System.Interactive/Catch.cs
  65. 49 0
      Ix.NET/Source/System.Interactive/Concatenate.cs
  66. 67 0
      Ix.NET/Source/System.Interactive/Create.cs
  67. 34 0
      Ix.NET/Source/System.Interactive/Defer.cs
  68. 157 0
      Ix.NET/Source/System.Interactive/Distinct.cs
  69. 157 0
      Ix.NET/Source/System.Interactive/Do.cs
  70. 28 0
      Ix.NET/Source/System.Interactive/Empty.cs
  71. 0 175
      Ix.NET/Source/System.Interactive/EnumerableEx.Aggregates.cs
  72. 0 649
      Ix.NET/Source/System.Interactive/EnumerableEx.Buffering.cs
  73. 0 192
      Ix.NET/Source/System.Interactive/EnumerableEx.Creation.cs
  74. 0 282
      Ix.NET/Source/System.Interactive/EnumerableEx.Exceptions.cs
  75. 0 158
      Ix.NET/Source/System.Interactive/EnumerableEx.Imperative.cs
  76. 0 98
      Ix.NET/Source/System.Interactive/EnumerableEx.Multiple.cs
  77. 0 679
      Ix.NET/Source/System.Interactive/EnumerableEx.Single.cs
  78. 48 0
      Ix.NET/Source/System.Interactive/Expand.cs
  79. 44 0
      Ix.NET/Source/System.Interactive/Finally.cs
  80. 42 0
      Ix.NET/Source/System.Interactive/For.cs
  81. 49 0
      Ix.NET/Source/System.Interactive/ForEach.cs
  82. 42 0
      Ix.NET/Source/System.Interactive/Generate.cs
  83. 38 0
      Ix.NET/Source/System.Interactive/Hide.cs
  84. 43 45
      Ix.NET/Source/System.Interactive/IYielder.cs
  85. 52 0
      Ix.NET/Source/System.Interactive/If.cs
  86. 36 0
      Ix.NET/Source/System.Interactive/IgnoreElements.cs
  87. 108 0
      Ix.NET/Source/System.Interactive/Max.cs
  88. 370 0
      Ix.NET/Source/System.Interactive/Memoize.cs
  89. 71 0
      Ix.NET/Source/System.Interactive/Min.cs
  90. 87 0
      Ix.NET/Source/System.Interactive/OnErrorResumeNext.cs
  91. 188 0
      Ix.NET/Source/System.Interactive/Publish.cs
  92. 83 0
      Ix.NET/Source/System.Interactive/Repeat.cs
  93. 48 0
      Ix.NET/Source/System.Interactive/Retry.cs
  94. 25 0
      Ix.NET/Source/System.Interactive/Return.cs
  95. 86 0
      Ix.NET/Source/System.Interactive/Scan.cs
  96. 32 0
      Ix.NET/Source/System.Interactive/SelectMany.cs
  97. 128 0
      Ix.NET/Source/System.Interactive/Share.cs
  98. 46 0
      Ix.NET/Source/System.Interactive/Skip.cs
  99. 38 0
      Ix.NET/Source/System.Interactive/StartsWith.cs
  100. 51 0
      Ix.NET/Source/System.Interactive/Take.cs

+ 115 - 0
Ix.NET/Source/System.Interactive.Async/Aggregate.cs

@@ -0,0 +1,115 @@
+// // Licensed to the .NET Foundation under one or more agreements.
+// // The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// // See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<TResult> Aggregate<TSource, TAccumulate, TResult>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (accumulator == null)
+                throw new ArgumentNullException("accumulator");
+            if (resultSelector == null)
+                throw new ArgumentNullException("resultSelector");
+
+            return Aggregate(source, seed, accumulator, resultSelector, CancellationToken.None);
+        }
+
+        public static Task<TAccumulate> Aggregate<TSource, TAccumulate>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (accumulator == null)
+                throw new ArgumentNullException("accumulator");
+
+            return Aggregate(source, seed, accumulator, CancellationToken.None);
+        }
+
+        public static Task<TSource> Aggregate<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (accumulator == null)
+                throw new ArgumentNullException("accumulator");
+
+            return Aggregate(source, accumulator, CancellationToken.None);
+        }
+
+        public static Task<TResult> Aggregate<TSource, TAccumulate, TResult>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (accumulator == null)
+                throw new ArgumentNullException(nameof(accumulator));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+
+            return Aggregate_(source, seed, accumulator, resultSelector, cancellationToken);
+        }
+
+        public static Task<TAccumulate> Aggregate<TSource, TAccumulate>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (accumulator == null)
+                throw new ArgumentNullException(nameof(accumulator));
+
+            return source.Aggregate(seed, accumulator, x => x, cancellationToken);
+        }
+
+        public static Task<TSource> Aggregate<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (accumulator == null)
+                throw new ArgumentNullException(nameof(accumulator));
+
+            return Aggregate_(source, accumulator, cancellationToken);
+        }
+
+        private static async Task<TResult> Aggregate_<TSource, TAccumulate, TResult>(IAsyncEnumerable<TSource> source, TAccumulate seed,
+                                                                                     Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector, CancellationToken cancellationToken)
+        {
+            var acc = seed;
+
+            using (var e = source.GetEnumerator())
+            {
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    acc = accumulator(acc, e.Current);
+                }
+            }
+
+            return resultSelector(acc);
+        }
+
+        private static async Task<TSource> Aggregate_<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator, CancellationToken cancellationToken)
+        {
+            var first = true;
+            var acc = default(TSource);
+
+            using (var e = source.GetEnumerator())
+            {
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    acc = first ? e.Current : accumulator(acc, e.Current);
+                    first = false;
+                }
+            }
+            if (first)
+                throw new InvalidOperationException(Strings.NO_ELEMENTS);
+            return acc;
+        }
+    }
+}

+ 100 - 0
Ix.NET/Source/System.Interactive.Async/AnyAll.cs

@@ -0,0 +1,100 @@
+// // Licensed to the .NET Foundation under one or more agreements.
+// // The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// // See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<bool> All<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (predicate == null)
+                throw new ArgumentNullException("predicate");
+
+            return All(source, predicate, CancellationToken.None);
+        }
+
+        public static Task<bool> All<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return All_(source, predicate, cancellationToken);
+        }
+
+        public static Task<bool> Any<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (predicate == null)
+                throw new ArgumentNullException("predicate");
+
+            return Any(source, predicate, CancellationToken.None);
+        }
+
+        public static Task<bool> Any<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Any(source, CancellationToken.None);
+        }
+
+        public static Task<bool> Any<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Any_(source, predicate, cancellationToken);
+        }
+
+        public static Task<bool> Any<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            var e = source.GetEnumerator();
+            return e.MoveNext(cancellationToken);
+        }
+
+        private static async Task<bool> All_<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    if (!predicate(e.Current))
+                        return false;
+                }
+            }
+            return true;
+        }
+
+        private static async Task<bool> Any_<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    if (predicate(e.Current))
+                        return true;
+                }
+            }
+            return false;
+        }
+    }
+}

+ 0 - 1739
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Aggregates.cs

@@ -1,1739 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using System.Threading;
-
-namespace System.Linq
-{
-    public static partial class AsyncEnumerable
-    {
-        public static Task<TResult> Aggregate<TSource, TAccumulate, TResult>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (accumulator == null)
-                throw new ArgumentNullException(nameof(accumulator));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-
-            return Aggregate_(source, seed, accumulator, resultSelector, cancellationToken);
-        }
-
-        private static async Task<TResult> Aggregate_<TSource, TAccumulate, TResult>(IAsyncEnumerable<TSource> source, TAccumulate seed,
-            Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector, CancellationToken cancellationToken)
-        {
-            var acc = seed;
-
-            using (var e = source.GetEnumerator())
-            {
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    acc = accumulator(acc, e.Current);
-                }
-            }
-
-            return resultSelector(acc);
-        }
-
-        public static Task<TAccumulate> Aggregate<TSource, TAccumulate>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (accumulator == null)
-                throw new ArgumentNullException(nameof(accumulator));
-
-            return source.Aggregate(seed, accumulator, x => x, cancellationToken);
-        }
-
-        public static Task<TSource> Aggregate<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (accumulator == null)
-                throw new ArgumentNullException(nameof(accumulator));
-
-            return Aggregate_(source, accumulator, cancellationToken);
-        }
-
-        private static async Task<TSource> Aggregate_<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator, CancellationToken cancellationToken)
-        {
-            var first = true;
-            var acc = default(TSource);
-
-            using (var e = source.GetEnumerator())
-            {
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    acc = first ? e.Current : accumulator(acc, e.Current);
-                    first = false;
-                }
-            }
-            if (first)
-                throw new InvalidOperationException(Strings.NO_ELEMENTS);
-            return acc;
-        }
-
-        public static Task<int> Count<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(0, (c, _) => checked(c + 1), cancellationToken);
-        }
-
-        public static Task<int> Count<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return source.Where(predicate).Aggregate(0, (c, _) => checked(c + 1), cancellationToken);
-        }
-
-        public static Task<long> LongCount<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(0L, (c, _) => checked(c + 1), cancellationToken);
-        }
-
-        public static Task<long> LongCount<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return source.Where(predicate).Aggregate(0L, (c, _) => checked(c + 1), cancellationToken);
-        }
-
-        public static Task<bool> All<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return All_(source, predicate, cancellationToken);
-        }
-
-        private static async Task<bool> All_<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    if (!predicate(e.Current))
-                        return false;
-                }
-            }
-            return true;
-        }
-
-        public static Task<bool> Any<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return Any_(source, predicate, cancellationToken);
-        }
-
-        private static async Task<bool> Any_<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    if (predicate(e.Current))
-                        return true;
-                }
-            }
-            return false;
-        }
-
-        public static Task<bool> Any<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            var e = source.GetEnumerator();
-            return e.MoveNext(cancellationToken);
-        }
-
-        public static Task<bool> Contains<TSource>(this IAsyncEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.Any(x => comparer.Equals(x, value), cancellationToken);
-        }
-
-        public static Task<bool> Contains<TSource>(this IAsyncEnumerable<TSource> source, TSource value, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Contains(value, EqualityComparer<TSource>.Default, cancellationToken);
-        }
-
-        public static Task<TSource> First<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return First_(source, cancellationToken);
-        }
-
-        private static async Task<TSource> First_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                if (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    return e.Current;
-                }
-            }
-            throw new InvalidOperationException(Strings.NO_ELEMENTS);
-        }
-
-        public static Task<TSource> First<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return source.Where(predicate).First(cancellationToken);
-        }
-
-        public static Task<TSource> FirstOrDefault<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return FirstOrDefault_(source, cancellationToken);
-        }
-
-        private static async Task<TSource> FirstOrDefault_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                if (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    return e.Current;
-                }
-            }
-            return default(TSource);
-        }
-
-        public static Task<TSource> FirstOrDefault<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return source.Where(predicate).FirstOrDefault(cancellationToken);
-        }
-
-        public static Task<TSource> Last<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Last_(source, cancellationToken);
-        }
-
-        private static async Task<TSource> Last_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            var last = default(TSource);
-            var hasLast = false;
-
-            using (var e = source.GetEnumerator())
-            {
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    hasLast = true;
-                    last = e.Current;
-                }
-            }
-            if (!hasLast)
-                throw new InvalidOperationException(Strings.NO_ELEMENTS);
-            return last;
-        }
-
-        public static Task<TSource> Last<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return source.Where(predicate).Last(cancellationToken);
-        }
-
-        public static Task<TSource> LastOrDefault<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return LastOrDefault_(source, cancellationToken);
-        }
-
-        private static async Task<TSource> LastOrDefault_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            var last = default(TSource);
-            var hasLast = false;
-
-            using (var e = source.GetEnumerator())
-            {
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    hasLast = true;
-                    last = e.Current;
-                }
-            }
-            return !hasLast ? default(TSource) : last;
-        }
-
-        public static Task<TSource> LastOrDefault<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return source.Where(predicate).LastOrDefault(cancellationToken);
-        }
-
-        public static Task<TSource> Single<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Single_(source, cancellationToken);
-        }
-
-        private static async Task<TSource> Single_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                if (!await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
-                }
-                var result = e.Current;
-                if (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    throw new InvalidOperationException(Strings.MORE_THAN_ONE_ELEMENT);
-                }
-                return result;
-            }
-        }
-
-        public static Task<TSource> Single<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return source.Where(predicate).Single(cancellationToken);
-        }
-
-        public static Task<TSource> SingleOrDefault<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return SingleOrDefault_(source, cancellationToken);
-        }
-
-        private static async Task<TSource> SingleOrDefault_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                if (!await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    return default(TSource);
-                }
-
-                var result = e.Current;
-                if (!await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    return result;
-                }
-            }
-            throw new InvalidOperationException(Strings.MORE_THAN_ONE_ELEMENT);
-        }
-
-        public static Task<TSource> SingleOrDefault<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return source.Where(predicate).SingleOrDefault(cancellationToken);
-        }
-
-        public static Task<TSource> ElementAt<TSource>(this IAsyncEnumerable<TSource> source, int index, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (index < 0)
-                throw new ArgumentOutOfRangeException(nameof(index));
-
-            return ElementAt_(source, index, cancellationToken);
-        }
-
-        private static async Task<TSource> ElementAt_<TSource>(IAsyncEnumerable<TSource> source, int index, CancellationToken cancellationToken)
-        {
-            if (index >= 0)
-            {
-                using (var e = source.GetEnumerator())
-                {
-                    while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                    {
-                        if (index == 0)
-                        {
-                            return e.Current;
-                        }
-
-                        index--;
-                    }
-                }
-            }
-
-            throw new ArgumentOutOfRangeException(nameof(index));
-        }
-
-        public static Task<TSource> ElementAtOrDefault<TSource>(this IAsyncEnumerable<TSource> source, int index, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (index < 0)
-                throw new ArgumentOutOfRangeException(nameof(index));
-
-            return ElementAtOrDefault_(source, index, cancellationToken);
-        }
-
-        private static async Task<TSource> ElementAtOrDefault_<TSource>(IAsyncEnumerable<TSource> source, int index, CancellationToken cancellationToken)
-        {
-            if (index >= 0)
-            {
-                using (var e = source.GetEnumerator())
-                {
-                    while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                    {
-                        if (index == 0)
-                        {
-                            return e.Current;
-                        }
-
-                        index--;
-                    }
-                }
-            }
-
-            return default(TSource);
-        }
-
-        public static Task<TSource[]> ToArray<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(new List<TSource>(), (list, x) => { list.Add(x); return list; }, list => list.ToArray(), cancellationToken);
-        }
-
-        public static Task<List<TSource>> ToList<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(new List<TSource>(), (list, x) => { list.Add(x); return list; }, cancellationToken);
-        }
-
-        public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (elementSelector == null)
-                throw new ArgumentNullException(nameof(elementSelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.Aggregate(new Dictionary<TKey, TElement>(comparer), (d, x) => { d.Add(keySelector(x), elementSelector(x)); return d; }, cancellationToken);
-        }
-
-        public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (elementSelector == null)
-                throw new ArgumentNullException(nameof(elementSelector));
-
-            return source.ToDictionary(keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
-        }
-
-        public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.ToDictionary(keySelector, x => x, comparer, cancellationToken);
-        }
-
-        public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return source.ToDictionary(keySelector, x => x, EqualityComparer<TKey>.Default, cancellationToken);
-        }
-
-        public static async Task<ILookup<TKey, TElement>> ToLookup<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (elementSelector == null)
-                throw new ArgumentNullException(nameof(elementSelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            var lookup = await Internal.Lookup<TKey, TElement>.CreateAsync(source, keySelector, elementSelector, comparer, cancellationToken).ConfigureAwait(false);
-
-            return lookup;
-        }
-
-        public static Task<ILookup<TKey, TElement>> ToLookup<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (elementSelector == null)
-                throw new ArgumentNullException(nameof(elementSelector));
-
-            return source.ToLookup(keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
-        }
-
-        public static Task<ILookup<TKey, TSource>> ToLookup<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.ToLookup(keySelector, x => x, comparer, cancellationToken);
-        }
-
-        public static Task<ILookup<TKey, TSource>> ToLookup<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return source.ToLookup(keySelector, x => x, EqualityComparer<TKey>.Default, cancellationToken);
-        }
-
-        public static Task<double> Average(this IAsyncEnumerable<int> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Average_(source, cancellationToken);
-        }
-
-        private static async Task<double> Average_(this IAsyncEnumerable<int> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                if (!await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
-                }
-
-                long sum = e.Current;
-                long count = 1;
-                checked
-                {
-                    while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                    {
-                        sum += e.Current;
-                        ++count;
-                    }
-                }
-
-                return (double)sum / count;
-            }
-        }
-
-        public static Task<double?> Average(this IAsyncEnumerable<int?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Average_(source, cancellationToken);
-        }
-
-        private static async Task<double?> Average_(IAsyncEnumerable<int?> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    var v = e.Current;
-                    if (v.HasValue)
-                    {
-                        long sum = v.GetValueOrDefault();
-                        long count = 1;
-                        checked
-                        {
-                            while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                            {
-                                v = e.Current;
-                                if (v.HasValue)
-                                {
-                                    sum += v.GetValueOrDefault();
-                                    ++count;
-                                }
-                            }
-                        }
-
-                        return (double)sum / count;
-                    }
-                }
-            }
-
-            return null;
-        }
-
-        public static Task<double> Average(this IAsyncEnumerable<long> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Average_(source, cancellationToken);
-        }
-
-        private static async Task<double> Average_(IAsyncEnumerable<long> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                if (!await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
-                }
-
-                var sum = e.Current;
-                long count = 1;
-                checked
-                {
-                    while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                    {
-                        sum += e.Current;
-                        ++count;
-                    }
-                }
-
-                return (double)sum / count;
-            }
-        }
-
-        public static Task<double?> Average(this IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Average_(source, cancellationToken);
-        }
-
-        private static async Task<double?> Average_(IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    var v = e.Current;
-                    if (v.HasValue)
-                    {
-                        var sum = v.GetValueOrDefault();
-                        long count = 1;
-                        checked
-                        {
-                            while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                            {
-                                v = e.Current;
-                                if (v.HasValue)
-                                {
-                                    sum += v.GetValueOrDefault();
-                                    ++count;
-                                }
-                            }
-                        }
-
-                        return (double)sum / count;
-                    }
-                }
-            }
-
-            return null;
-        }
-
-        public static Task<double> Average(this IAsyncEnumerable<double> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Average_(source, cancellationToken);
-        }
-
-        private static async Task<double> Average_(IAsyncEnumerable<double> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                if (!await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
-                }
-
-                var sum = e.Current;
-                long count = 1;
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    // There is an opportunity to short-circuit here, in that if e.Current is
-                    // ever NaN then the result will always be NaN. Assuming that this case is
-                    // rare enough that not checking is the better approach generally.
-                    sum += e.Current;
-                    ++count;
-                }
-
-                return sum / count;
-            }
-        }
-
-        public static Task<double?> Average(this IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Average_(source, cancellationToken);
-        }
-
-        private static async Task<double?> Average_(IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    var v = e.Current;
-                    if (v.HasValue)
-                    {
-                        var sum = v.GetValueOrDefault();
-                        long count = 1;
-                        checked
-                        {
-                            while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                            {
-                                v = e.Current;
-                                if (v.HasValue)
-                                {
-                                    sum += v.GetValueOrDefault();
-                                    ++count;
-                                }
-                            }
-                        }
-
-                        return sum / count;
-                    }
-                }
-            }
-
-            return null;
-        }
-
-        public static Task<float> Average(this IAsyncEnumerable<float> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Average_(source, cancellationToken);
-        }
-
-        private static async Task<float> Average_(IAsyncEnumerable<float> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                if (!await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
-                }
-
-                double sum = e.Current;
-                long count = 1;
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    sum += e.Current;
-                    ++count;
-                }
-
-                return (float)(sum / count);
-            }
-        }
-
-        public static Task<float?> Average(this IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Average_(source, cancellationToken);
-        }
-
-        private static async Task<float?> Average_(IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    var v = e.Current;
-                    if (v.HasValue)
-                    {
-                        double sum = v.GetValueOrDefault();
-                        long count = 1;
-                        checked
-                        {
-                            while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                            {
-                                v = e.Current;
-                                if (v.HasValue)
-                                {
-                                    sum += v.GetValueOrDefault();
-                                    ++count;
-                                }
-                            }
-                        }
-
-                        return (float)(sum / count);
-                    }
-                }
-            }
-
-            return null;
-        }
-
-        public static Task<decimal> Average(this IAsyncEnumerable<decimal> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Average_(source, cancellationToken);
-        }
-
-        private static async Task<decimal> Average_(IAsyncEnumerable<decimal> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                if (!await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
-                }
-
-                var sum = e.Current;
-                long count = 1;
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    sum += e.Current;
-                    ++count;
-                }
-
-                return sum / count;
-            }
-        }
-
-        public static Task<decimal?> Average(this IAsyncEnumerable<decimal?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Average_(source, cancellationToken);
-        }
-
-        private static async Task<decimal?> Average_(IAsyncEnumerable<decimal?> source, CancellationToken cancellationToken)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    var v = e.Current;
-                    if (v.HasValue)
-                    {
-                        var sum = v.GetValueOrDefault();
-                        long count = 1;
-                        while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                        {
-                            v = e.Current;
-                            if (v.HasValue)
-                            {
-                                sum += v.GetValueOrDefault();
-                                ++count;
-                            }
-                        }
-
-                        return sum / count;
-                    }
-                }
-            }
-
-            return null;
-        }
-
-        public static Task<double?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Average(cancellationToken);
-        }
-
-        public static Task<double> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Average(cancellationToken);
-        }
-
-        public static Task<double> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Average(cancellationToken);
-        }
-
-        public static Task<double?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Average(cancellationToken);
-        }
-
-        public static Task<double> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Average(cancellationToken);
-        }
-
-        public static Task<double?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Average(cancellationToken);
-        }
-
-        public static Task<float> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Average(cancellationToken);
-        }
-
-        public static Task<float?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Average(cancellationToken);
-        }
-
-        public static Task<decimal> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Average(cancellationToken);
-        }
-
-        public static Task<decimal?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Average(cancellationToken);
-        }
-
-        public static Task<int> Max(this IAsyncEnumerable<int> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(Math.Max, cancellationToken);
-        }
-
-        public static Task<long> Max(this IAsyncEnumerable<long> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(Math.Max, cancellationToken);
-        }
-
-        public static Task<double> Max(this IAsyncEnumerable<double> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(Math.Max, cancellationToken);
-        }
-
-        public static Task<float> Max(this IAsyncEnumerable<float> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(Math.Max, cancellationToken);
-        }
-
-        public static Task<decimal> Max(this IAsyncEnumerable<decimal> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(Math.Max, cancellationToken);
-        }
-
-        static T? NullableMax<T>(T? x, T? y)
-            where T : struct, IComparable<T>
-        {
-            if (!x.HasValue)
-                return y;
-            if (!y.HasValue)
-                return x;
-            if (x.Value.CompareTo(y.Value) >= 0)
-                return x;
-            return y;
-        }
-
-        public static Task<int?> Max(this IAsyncEnumerable<int?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(default(int?), NullableMax, cancellationToken);
-        }
-
-        public static Task<long?> Max(this IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(default(long?), NullableMax, cancellationToken);
-        }
-
-        public static Task<double?> Max(this IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(default(double?), NullableMax, cancellationToken);
-        }
-
-        public static Task<float?> Max(this IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(default(float?), NullableMax, cancellationToken);
-        }
-
-        public static Task<decimal?> Max(this IAsyncEnumerable<decimal?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(default(decimal?), NullableMax, cancellationToken);
-        }
-
-        public static Task<TSource> Max<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            var comparer = Comparer<TSource>.Default;
-            return source.Aggregate((x, y) => comparer.Compare(x, y) >= 0 ? x : y, cancellationToken);
-        }
-
-        public static Task<int> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Max(cancellationToken);
-        }
-
-        public static Task<long> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Max(cancellationToken);
-        }
-
-        public static Task<double> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Max(cancellationToken);
-        }
-
-        public static Task<float> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Max(cancellationToken);
-        }
-
-        public static Task<decimal> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Max(cancellationToken);
-        }
-
-        public static Task<int?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Max(cancellationToken);
-        }
-
-        public static Task<long?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Max(cancellationToken);
-        }
-
-        public static Task<double?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Max(cancellationToken);
-        }
-
-        public static Task<float?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Max(cancellationToken);
-        }
-
-        public static Task<decimal?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Max(cancellationToken);
-        }
-
-        public static Task<TResult> Max<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Max(cancellationToken);
-        }
-
-        public static Task<int> Min(this IAsyncEnumerable<int> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(Math.Min, cancellationToken);
-        }
-
-        public static Task<long> Min(this IAsyncEnumerable<long> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(Math.Min, cancellationToken);
-        }
-
-        public static Task<double> Min(this IAsyncEnumerable<double> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(Math.Min, cancellationToken);
-        }
-
-        public static Task<float> Min(this IAsyncEnumerable<float> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(Math.Min, cancellationToken);
-        }
-
-        public static Task<decimal> Min(this IAsyncEnumerable<decimal> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(Math.Min, cancellationToken);
-        }
-
-        static T? NullableMin<T>(T? x, T? y)
-            where T : struct, IComparable<T>
-        {
-            if (!x.HasValue)
-                return y;
-            if (!y.HasValue)
-                return x;
-            if (x.Value.CompareTo(y.Value) <= 0)
-                return x;
-            return y;
-        }
-
-        public static Task<int?> Min(this IAsyncEnumerable<int?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(default(int?), NullableMin, cancellationToken);
-        }
-
-        public static Task<long?> Min(this IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(default(long?), NullableMin, cancellationToken);
-        }
-
-        public static Task<double?> Min(this IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(default(double?), NullableMin, cancellationToken);
-        }
-
-        public static Task<float?> Min(this IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(default(float?), NullableMin, cancellationToken);
-        }
-
-        public static Task<decimal?> Min(this IAsyncEnumerable<decimal?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(default(decimal?), NullableMin, cancellationToken);
-        }
-
-        public static Task<TSource> Min<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            var comparer = Comparer<TSource>.Default;
-            return source.Aggregate((x, y) => comparer.Compare(x, y) <= 0 ? x : y, cancellationToken);
-        }
-
-        public static Task<int> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Min(cancellationToken);
-        }
-
-        public static Task<long> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Min(cancellationToken);
-        }
-
-        public static Task<double> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Min(cancellationToken);
-        }
-
-        public static Task<float> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Min(cancellationToken);
-        }
-
-        public static Task<decimal> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Min(cancellationToken);
-        }
-
-        public static Task<int?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Min(cancellationToken);
-        }
-
-        public static Task<long?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Min(cancellationToken);
-        }
-
-        public static Task<double?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Min(cancellationToken);
-        }
-
-        public static Task<float?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Min(cancellationToken);
-        }
-
-        public static Task<decimal?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Min(cancellationToken);
-        }
-
-        public static Task<TResult> Min<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Min(cancellationToken);
-        }
-
-        public static Task<int> Sum(this IAsyncEnumerable<int> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(0, (x, y) => x + y, cancellationToken);
-        }
-
-        public static Task<long> Sum(this IAsyncEnumerable<long> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(0L, (x, y) => x + y, cancellationToken);
-        }
-
-        public static Task<double> Sum(this IAsyncEnumerable<double> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(0.0, (x, y) => x + y, cancellationToken);
-        }
-
-        public static Task<float> Sum(this IAsyncEnumerable<float> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(0f, (x, y) => x + y, cancellationToken);
-        }
-
-        public static Task<decimal> Sum(this IAsyncEnumerable<decimal> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate(0m, (x, y) => x + y, cancellationToken);
-        }
-
-        public static Task<int?> Sum(this IAsyncEnumerable<int?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate((int?)0, (x, y) => x + y.GetValueOrDefault(), cancellationToken);
-        }
-
-        public static Task<long?> Sum(this IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate((long?)0, (x, y) => x + y.GetValueOrDefault(), cancellationToken);
-        }
-
-        public static Task<double?> Sum(this IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate((double?)0, (x, y) => x + y.GetValueOrDefault(), cancellationToken);
-        }
-
-        public static Task<float?> Sum(this IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate((float?)0, (x, y) => x + y.GetValueOrDefault(), cancellationToken);
-        }
-
-        public static Task<decimal?> Sum(this IAsyncEnumerable<decimal?> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Aggregate((decimal?)0, (x, y) => x + y.GetValueOrDefault(), cancellationToken);
-        }
-
-        public static Task<int> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Sum(cancellationToken);
-        }
-
-        public static Task<long> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Sum(cancellationToken);
-        }
-
-        public static Task<double> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Sum(cancellationToken);
-        }
-
-        public static Task<float> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Sum(cancellationToken);
-        }
-
-        public static Task<decimal> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Sum(cancellationToken);
-        }
-
-        public static Task<int?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Sum(cancellationToken);
-        }
-
-        public static Task<long?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Sum(cancellationToken);
-        }
-
-        public static Task<double?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Sum(cancellationToken);
-        }
-
-        public static Task<float?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Sum(cancellationToken);
-        }
-
-        public static Task<decimal?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Select(selector).Sum(cancellationToken);
-        }
-
-        public static Task<bool> IsEmpty<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return IsEmpty_(source, cancellationToken);
-        }
-
-        private static async Task<bool> IsEmpty_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
-        {
-            return !await source.Any(cancellationToken).ConfigureAwait(false);
-        }
-
-        public static Task<TSource> Min<TSource>(this IAsyncEnumerable<TSource> source, IComparer<TSource> comparer, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return Min_(source, comparer, cancellationToken);
-        }
-
-        private static async Task<TSource> Min_<TSource>(IAsyncEnumerable<TSource> source, IComparer<TSource> comparer, CancellationToken cancellationToken)
-        {
-            return (await MinBy(source, x => x, comparer, cancellationToken).ConfigureAwait(false)).First();
-        }
-
-        public static Task<IList<TSource>> MinBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return MinBy(source, keySelector, Comparer<TKey>.Default, cancellationToken);
-        }
-
-        public static Task<IList<TSource>> MinBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return ExtremaBy(source, keySelector, (key, minValue) => -comparer.Compare(key, minValue), cancellationToken);
-        }
-
-        public static Task<TSource> Max<TSource>(this IAsyncEnumerable<TSource> source, IComparer<TSource> comparer, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return Max_(source, comparer, cancellationToken);
-        }
-
-        private static async Task<TSource> Max_<TSource>(IAsyncEnumerable<TSource> source, IComparer<TSource> comparer, CancellationToken cancellationToken)
-        {
-            return (await MaxBy(source, x => x, comparer, cancellationToken).ConfigureAwait(false)).First();
-        }
-
-        public static Task<IList<TSource>> MaxBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return MaxBy(source, keySelector, Comparer<TKey>.Default, cancellationToken);
-        }
-
-        public static Task<IList<TSource>> MaxBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return ExtremaBy(source, keySelector, (key, minValue) => comparer.Compare(key, minValue), cancellationToken);
-        }
-
-        private static async Task<IList<TSource>> ExtremaBy<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, TKey, int> compare, CancellationToken cancellationToken)
-        {
-            var result = new List<TSource>();
-
-            using (var e = source.GetEnumerator())
-            {
-                if (!await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
-
-                var current = e.Current;
-                var resKey = keySelector(current);
-                result.Add(current);
-
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    var cur = e.Current;
-                    var key = keySelector(cur);
-
-                    var cmp = compare(key, resKey);
-                    if (cmp == 0)
-                    {
-                        result.Add(cur);
-                    }
-                    else if (cmp > 0)
-                    {
-                        result = new List<TSource> { cur };
-                        resKey = key;
-                    }
-                }
-            }
-
-            return result;
-        }
-    }
-}

+ 0 - 295
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Conversions.cs

@@ -1,295 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using System.Threading;
-
-namespace System.Linq
-{
-    public static partial class AsyncEnumerable
-    {
-        public static IAsyncEnumerable<TSource> ToAsyncEnumerable<TSource>(this IEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                return Create(
-                    ct => Task.Run(() =>
-                    {
-                        var res = false;
-                        try
-                        {
-                            res = e.MoveNext();
-                        }
-                        finally
-                        {
-                            if (!res)
-                                e.Dispose();
-                        }
-                        return res;
-                    }, ct),
-                    () => e.Current,
-                    () => e.Dispose()
-                );
-            });
-        }
-
-        public static IEnumerable<TSource> ToEnumerable<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return ToEnumerable_(source);
-        }
-
-        private static IEnumerable<TSource> ToEnumerable_<TSource>(IAsyncEnumerable<TSource> source)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                while (true)
-                {
-                    if (!e.MoveNext(CancellationToken.None).Result)
-                        break;
-                    var c = e.Current;
-                    yield return c;
-                }
-            }
-        }
-
-        public static IAsyncEnumerable<TSource> ToAsyncEnumerable<TSource>(this Task<TSource> task)
-        {
-            if (task == null)
-                throw new ArgumentNullException(nameof(task));
-            
-            return Create(() =>
-            {
-                var called = 0;
-
-                var value = default(TSource);
-                return Create(
-                    async ct =>
-                    {
-                        if (Interlocked.CompareExchange(ref called, 1, 0) == 0)
-                        {
-                            value = await task.ConfigureAwait(false);
-                            return true;
-                        }
-                        return false;
-                    },
-                    () => value,
-                    () => { });
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> ToAsyncEnumerable<TSource>(this IObservable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Create(() =>
-            {
-                var observer = new ToAsyncEnumerableObserver<TSource>();
-
-                var subscription = source.Subscribe(observer);
-
-                return Create(
-                    (ct, tcs) =>
-                    {
-                        var hasValue = false;
-                        var hasCompleted = false;
-                        var error = default(Exception);
-
-                        lock (observer.SyncRoot)
-                        {
-                            if (observer.Values.Count > 0)
-                            {
-                                hasValue = true;
-                                observer.Current = observer.Values.Dequeue();
-                            }
-                            else if (observer.HasCompleted)
-                            {
-                                hasCompleted = true;
-                            }
-                            else if (observer.Error != null)
-                            {
-                                error = observer.Error;
-                            }
-                            else
-                            {
-                                observer.TaskCompletionSource = tcs;
-                            }
-                        }
-
-                        if (hasValue)
-                        {
-                            tcs.TrySetResult(true);
-                        }
-                        else if (hasCompleted)
-                        {
-                            tcs.TrySetResult(false);
-                        }
-                        else if (error != null)
-                        {
-                            tcs.TrySetException(error);
-                        }
-
-                        return tcs.Task;
-                    },
-                    () => observer.Current,
-                    () =>
-                    {
-                        subscription.Dispose();
-                        // Should we cancel in-flight operations somehow?
-                    });
-            });
-        }
-
-        class ToAsyncEnumerableObserver<T> : IObserver<T>
-        {
-            public ToAsyncEnumerableObserver()
-            {
-                Values = new Queue<T>();
-            }
-
-            public object SyncRoot
-            {
-                get { return Values; }
-            }
-
-            public readonly Queue<T> Values;
-            public Exception Error;
-            public bool HasCompleted;
-
-            public T Current;
-            public TaskCompletionSource<bool> TaskCompletionSource;
-
-            public void OnCompleted()
-            {
-                var tcs = default(TaskCompletionSource<bool>);
-
-                lock (SyncRoot)
-                {
-                    HasCompleted = true;
-
-                    if (TaskCompletionSource != null)
-                    {
-                        tcs = TaskCompletionSource;
-                        TaskCompletionSource = null;
-                    }
-                }
-
-                if (tcs != null)
-                {
-                    tcs.SetResult(false);
-                }
-            }
-
-            public void OnError(Exception error)
-            {
-                var tcs = default(TaskCompletionSource<bool>);
-
-                lock (SyncRoot)
-                {
-                    Error = error;
-
-                    if (TaskCompletionSource != null)
-                    {
-                        tcs = TaskCompletionSource;
-                        TaskCompletionSource = null;
-                    }
-                }
-
-                if (tcs != null)
-                {
-                    tcs.SetException(error);
-                }
-            }
-
-            public void OnNext(T value)
-            {
-                var tcs = default(TaskCompletionSource<bool>);
-
-                lock (SyncRoot)
-                {
-                    if (TaskCompletionSource == null)
-                    {
-                        Values.Enqueue(value);
-                    }
-                    else
-                    {
-                        Current = value;
-
-                        tcs = TaskCompletionSource;
-                        TaskCompletionSource = null;
-                    }
-                }
-
-                if (tcs != null)
-                {
-                    tcs.SetResult(true);
-                }
-            }
-        }
-
-        public static IObservable<TSource> ToObservable<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return new ToObservableObservable<TSource>(source);
-        }
-
-        class ToObservableObservable<T> : IObservable<T>
-        {
-            private readonly IAsyncEnumerable<T> source;
-
-            public ToObservableObservable(IAsyncEnumerable<T> source)
-            {
-                this.source = source;
-            }
-
-            public IDisposable Subscribe(IObserver<T> observer)
-            {
-                var ctd = new CancellationTokenDisposable();
-                var e = source.GetEnumerator();
-
-                var f = default(Action);
-                f = () => e.MoveNext(ctd.Token).ContinueWith(t =>
-                {
-                    if (t.IsFaulted)
-                    {
-                        observer.OnError(t.Exception);
-                        e.Dispose();
-                    }
-                    else if (t.IsCanceled)
-                    {
-                        e.Dispose();
-                    }
-                    else if (t.IsCompleted)
-                    {
-                        if (t.Result)
-                        {
-                            observer.OnNext(e.Current);
-                            f();
-                        }
-                        else
-                        {
-                            observer.OnCompleted();
-                            e.Dispose();
-                        }
-                    }
-                }, ctd.Token);
-
-                f();
-
-                return Disposable.Create(ctd, e);
-            }
-        }
-    }
-}

+ 0 - 303
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Creation.cs

@@ -1,303 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace System.Linq
-{
-    public static partial class AsyncEnumerable
-    {
-        public static IAsyncEnumerable<T> Create<T>(Func<IAsyncEnumerator<T>> getEnumerator)
-        {
-            return new AnonymousAsyncEnumerable<T>(getEnumerator);
-        }
-
-        private class AnonymousAsyncEnumerable<T> : IAsyncEnumerable<T>
-        {
-            private Func<IAsyncEnumerator<T>> getEnumerator;
-
-            public AnonymousAsyncEnumerable(Func<IAsyncEnumerator<T>> getEnumerator)
-            {
-                this.getEnumerator = getEnumerator;
-            }
-
-            public IAsyncEnumerator<T> GetEnumerator()
-            {
-                return getEnumerator();
-            }
-        }
-
-        private static IAsyncEnumerator<T> Create<T>(Func<CancellationToken, Task<bool>> moveNext, Func<T> current,
-            Action dispose, IDisposable enumerator)
-        {
-            return Create(async ct =>
-            {
-                using (ct.Register(dispose))
-                {
-                    try
-                    {
-                        var result = await moveNext(ct).ConfigureAwait(false);
-                        if (!result)
-                        {
-                            enumerator?.Dispose();
-                        }
-                        return result;
-                    }
-                    catch
-                    {
-                        enumerator?.Dispose();
-                        throw;
-                    }
-                }
-            }, current, dispose);
-        }
-
-        public static IAsyncEnumerator<T> Create<T>(Func<CancellationToken, Task<bool>> moveNext, Func<T> current, Action dispose)
-        {
-            return new AnonymousAsyncEnumerator<T>(moveNext, current, dispose);
-        }
-
-        private static IAsyncEnumerator<T> Create<T>(Func<CancellationToken, TaskCompletionSource<bool>, Task<bool>> moveNext, Func<T> current, Action dispose)
-        {
-            var self = default(IAsyncEnumerator<T>);
-            self = new AnonymousAsyncEnumerator<T>(
-                async ct =>
-                {
-                    var tcs = new TaskCompletionSource<bool>();
-
-                    var stop = new Action(() =>
-                    {
-                        self.Dispose();
-                        tcs.TrySetCanceled();
-                    });
-
-                    using (ct.Register(stop))
-                    {
-                        return await moveNext(ct, tcs).ConfigureAwait(false);
-                    }
-                },
-                current,
-                dispose
-            );
-            return self;
-        }
-
-        private class AnonymousAsyncEnumerator<T> : IAsyncEnumerator<T>
-        {
-            private readonly Func<CancellationToken, Task<bool>> _moveNext;
-            private readonly Func<T> _current;
-            private readonly Action _dispose;
-            private bool _disposed;
-
-            public AnonymousAsyncEnumerator(Func<CancellationToken, Task<bool>> moveNext, Func<T> current, Action dispose)
-            {
-                _moveNext = moveNext;
-                _current = current;
-                _dispose = dispose;
-            }
-
-            public Task<bool> MoveNext(CancellationToken cancellationToken)
-            {
-                if (_disposed)
-                    return TaskExt.False;
-
-                return _moveNext(cancellationToken);
-            }
-
-            public T Current
-            {
-                get
-                {
-                    return _current();
-                }
-            }
-
-            public void Dispose()
-            {
-                if (!_disposed)
-                {
-                    _disposed = true;
-                    _dispose();
-                }
-            }
-        }
-
-        public static IAsyncEnumerable<TValue> Return<TValue>(TValue value)
-        {
-            return new[] { value }.ToAsyncEnumerable();
-        }
-
-        public static IAsyncEnumerable<TValue> Throw<TValue>(Exception exception)
-        {
-            if (exception == null)
-                throw new ArgumentNullException(nameof(exception));
-
-            return Create(() => Create<TValue>(
-                ct => TaskExt.Throw<bool>(exception),
-                () => { throw new InvalidOperationException(); },
-                () => { })
-            );
-        }
-
-        public static IAsyncEnumerable<TValue> Never<TValue>()
-        {
-            return Create(() => Create<TValue>(
-                (ct, tcs) => tcs.Task,
-                () => { throw new InvalidOperationException(); },
-                () => { })
-            );
-        }
-
-        public static IAsyncEnumerable<TValue> Empty<TValue>()
-        {
-            return Create(() => Create<TValue>(
-                ct => TaskExt.False,
-                () => { throw new InvalidOperationException(); },
-                () => { })
-            );
-        }
-
-        public static IAsyncEnumerable<int> Range(int start, int count)
-        {
-            if (count < 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-
-            return Enumerable.Range(start, count).ToAsyncEnumerable();
-        }
-
-        public static IAsyncEnumerable<TResult> Repeat<TResult>(TResult element, int count)
-        {
-            if (count < 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-
-            return Enumerable.Repeat(element, count).ToAsyncEnumerable();
-        }
-
-        public static IAsyncEnumerable<TResult> Repeat<TResult>(TResult element)
-        {
-            return Create(() =>
-            {
-                return Create(
-                    ct => TaskExt.True,
-                    () => element,
-                    () => { }
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Defer<TSource>(Func<IAsyncEnumerable<TSource>> factory)
-        {
-            if (factory == null)
-                throw new ArgumentNullException(nameof(factory));
-
-            return Create(() => factory().GetEnumerator());
-        }
-
-        public static IAsyncEnumerable<TResult> Generate<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector)
-        {
-            if (condition == null)
-                throw new ArgumentNullException(nameof(condition));
-            if (iterate == null)
-                throw new ArgumentNullException(nameof(iterate));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-
-            return Create(() =>
-            {
-                var i = initialState;
-                var started = false;
-                var current = default(TResult);
-
-                return Create(
-                    ct =>
-                    {
-                        var b = false;
-                        try
-                        {
-                            if (started)
-                                i = iterate(i);
-
-                            b = condition(i);
-
-                            if (b)
-                                current = resultSelector(i);
-                        }
-                        catch (Exception ex)
-                        {
-                            return TaskExt.Throw<bool>(ex);
-                        }
-
-                        if (!b)
-                            return TaskExt.False;
-
-                        if (!started)
-                            started = true;
-
-                        return TaskExt.True;
-                    },
-                    () => current,
-                    () => { }
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Using<TSource, TResource>(Func<TResource> resourceFactory, Func<TResource, IAsyncEnumerable<TSource>> enumerableFactory) where TResource : IDisposable
-        {
-            if (resourceFactory == null)
-                throw new ArgumentNullException(nameof(resourceFactory));
-            if (enumerableFactory == null)
-                throw new ArgumentNullException(nameof(enumerableFactory));
-
-            return Create(() =>
-            {
-                var resource = resourceFactory();
-                var e = default(IAsyncEnumerator<TSource>);
-
-                try
-                {
-                    e = enumerableFactory(resource).GetEnumerator();
-                }
-                catch (Exception)
-                {
-                    resource.Dispose();
-                    throw;
-                }
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, resource, e);
-
-                var current = default(TSource);
-
-                return Create(
-                    async ct =>
-                    {
-                        bool res;
-                        try
-                        {
-                            res = await e.MoveNext(cts.Token).ConfigureAwait(false);
-                        }
-                        catch (Exception)
-                        {
-                            d.Dispose();
-                            throw;
-                        }
-                        if (res)
-                        {
-                            current = e.Current;
-                            return true;
-                        }
-                        d.Dispose();
-                        return false;
-                    },
-                    () => current,
-                    d.Dispose,
-                    null
-                );
-            });
-        }
-    }
-}

+ 0 - 279
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Exceptions.cs

@@ -1,279 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.ExceptionServices;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace System.Linq
-{
-    public static partial class AsyncEnumerable
-    {
-        public static IAsyncEnumerable<TSource> Catch<TSource, TException>(this IAsyncEnumerable<TSource> source, Func<TException, IAsyncEnumerable<TSource>> handler)
-            where TException : Exception
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (handler == null)
-                throw new ArgumentNullException(nameof(handler));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var a = new AssignableDisposable { Disposable = e };
-                var d = Disposable.Create(cts, a);
-                var done = false;
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (!done)
-                    {
-                        try
-                        {
-                            return await e.MoveNext(ct).ConfigureAwait(false);
-                        }
-                        catch (TException ex)
-                        {
-                            var err = handler(ex).GetEnumerator();
-                            e = err;
-                            a.Disposable = e;
-                            done = true;
-                            return await f(ct).ConfigureAwait(false);
-                        }
-                    }
-                    return await e.MoveNext(ct).ConfigureAwait(false);
-                };
-
-                return Create(
-                    f,
-                    () => e.Current,
-                    d.Dispose,
-                    a
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Catch<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
-        {
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return sources.Catch_();
-        }
-
-        public static IAsyncEnumerable<TSource> Catch<TSource>(params IAsyncEnumerable<TSource>[] sources)
-        {
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return sources.Catch_();
-        }
-
-        public static IAsyncEnumerable<TSource> Catch<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-
-            return new[] { first, second }.Catch_();
-        }
-
-        private static IAsyncEnumerable<TSource> Catch_<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
-        {
-            return Create(() =>
-            {
-                var se = sources.GetEnumerator();
-                var e = default(IAsyncEnumerator<TSource>);
-
-                var cts = new CancellationTokenDisposable();
-                var a = new AssignableDisposable();
-                var d = Disposable.Create(cts, se, a);
-
-                var error = default(ExceptionDispatchInfo);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (e == null)
-                    {
-                        if (se.MoveNext())
-                        {
-                            e = se.Current.GetEnumerator();
-                        }
-                        else
-                        {
-                            error?.Throw();
-                            return false;
-                        }
-
-                        error = null;
-
-                        a.Disposable = e;
-                    }
-
-                    try
-                    {
-                        return await e.MoveNext(ct).ConfigureAwait(false);
-                    }
-                    catch (Exception exception)
-                    {
-                        e.Dispose();
-                        e = null;
-                        error = ExceptionDispatchInfo.Capture(exception);
-                        return await f(ct).ConfigureAwait(false);
-                    }
-                };
-
-                return Create(
-                    f,
-                    () => e.Current,
-                    d.Dispose,
-                    a
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Finally<TSource>(this IAsyncEnumerable<TSource> source, Action finallyAction)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (finallyAction == null)
-                throw new ArgumentNullException(nameof(finallyAction));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var r = new Disposable(finallyAction);
-                var d = Disposable.Create(cts, e, r);
-
-                return Create(
-                    ct => e.MoveNext(ct),
-                    () => e.Current,
-                    d.Dispose,
-                    r
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> OnErrorResumeNext<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-
-            return OnErrorResumeNext_(new[] { first, second });
-        }
-
-        public static IAsyncEnumerable<TSource> OnErrorResumeNext<TSource>(params IAsyncEnumerable<TSource>[] sources)
-        {
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return OnErrorResumeNext_(sources);
-        }
-
-        public static IAsyncEnumerable<TSource> OnErrorResumeNext<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
-        {
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return OnErrorResumeNext_(sources);
-        }
-
-        private static IAsyncEnumerable<TSource> OnErrorResumeNext_<TSource>(IEnumerable<IAsyncEnumerable<TSource>> sources)
-        {
-            return Create(() =>
-            {
-                var se = sources.GetEnumerator();
-                var e = default(IAsyncEnumerator<TSource>);
-
-                var cts = new CancellationTokenDisposable();
-                var a = new AssignableDisposable();
-                var d = Disposable.Create(cts, se, a);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (e == null)
-                    {
-                        var b = false;
-                        b = se.MoveNext();
-                        if (b)
-                            e = se.Current.GetEnumerator();
-                        else
-                        {
-                            return false;
-                        }
-
-                        a.Disposable = e;
-                    }
-
-                    try
-                    {
-                        if (await e.MoveNext(ct).ConfigureAwait(false))
-                        {
-                            return true;
-                        }
-                    }
-                    catch
-                    {
-                        // ignore
-                    }
-
-                    e.Dispose();
-                    e = null;
-                    return await f(ct).ConfigureAwait(false);
-                };
-
-                return Create(
-                    f,
-                    () => e.Current,
-                    d.Dispose,
-                    a
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Retry<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return new[] { source }.Repeat().Catch();
-        }
-
-        public static IAsyncEnumerable<TSource> Retry<TSource>(this IAsyncEnumerable<TSource> source, int retryCount)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (retryCount < 0)
-                throw new ArgumentOutOfRangeException(nameof(retryCount));
-
-            return new[] { source }.Repeat(retryCount).Catch();
-        }
-
-        private static IEnumerable<TSource> Repeat<TSource>(this IEnumerable<TSource> source)
-        {
-            while (true)
-                foreach (var item in source)
-                    yield return item;
-        }
-
-        private static IEnumerable<TSource> Repeat<TSource>(this IEnumerable<TSource> source, int count)
-        {
-            for (var i = 0; i < count; i++)
-                foreach (var item in source)
-                    yield return item;
-        }
-    }
-}

+ 0 - 1252
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Generated.cs

@@ -1,1252 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace System.Linq
-{
-    public static partial class AsyncEnumerable
-    {
-        public static Task<decimal?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Min(source, selector, CancellationToken.None);
-        }
-
-        public static Task<TResult> Min<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Min(source, selector, CancellationToken.None);
-        }
-
-        public static Task<int> Sum(this IAsyncEnumerable<int> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Sum(source, CancellationToken.None);
-        }
-
-        public static Task<long> Sum(this IAsyncEnumerable<long> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Sum(source, CancellationToken.None);
-        }
-
-        public static Task<double> Sum(this IAsyncEnumerable<double> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Sum(source, CancellationToken.None);
-        }
-
-        public static Task<float> Sum(this IAsyncEnumerable<float> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Sum(source, CancellationToken.None);
-        }
-
-        public static Task<decimal> Sum(this IAsyncEnumerable<decimal> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Sum(source, CancellationToken.None);
-        }
-
-        public static Task<int?> Sum(this IAsyncEnumerable<int?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Sum(source, CancellationToken.None);
-        }
-
-        public static Task<long?> Sum(this IAsyncEnumerable<long?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Sum(source, CancellationToken.None);
-        }
-
-        public static Task<double?> Sum(this IAsyncEnumerable<double?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Sum(source, CancellationToken.None);
-        }
-
-        public static Task<float?> Sum(this IAsyncEnumerable<float?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Sum(source, CancellationToken.None);
-        }
-
-        public static Task<decimal?> Sum(this IAsyncEnumerable<decimal?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Sum(source, CancellationToken.None);
-        }
-
-        public static Task<int> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Sum(source, selector, CancellationToken.None);
-        }
-
-        public static Task<long> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Sum(source, selector, CancellationToken.None);
-        }
-
-        public static Task<double> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Sum(source, selector, CancellationToken.None);
-        }
-
-        public static Task<float> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Sum(source, selector, CancellationToken.None);
-        }
-
-        public static Task<decimal> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Sum(source, selector, CancellationToken.None);
-        }
-
-        public static Task<int?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Sum(source, selector, CancellationToken.None);
-        }
-
-        public static Task<long?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Sum(source, selector, CancellationToken.None);
-        }
-
-        public static Task<double?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Sum(source, selector, CancellationToken.None);
-        }
-
-        public static Task<float?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Sum(source, selector, CancellationToken.None);
-        }
-
-        public static Task<decimal?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Sum(source, selector, CancellationToken.None);
-        }
-
-        public static void ForEach<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> action)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (action == null)
-                throw new ArgumentNullException("action");
-
-            source.ForEachAsync(action).Wait();
-        }
-
-        public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> action)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (action == null)
-                throw new ArgumentNullException("action");
-
-            return ForEachAsync(source, action, CancellationToken.None);
-        }
-
-        public static void ForEach<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource, int> action)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (action == null)
-                throw new ArgumentNullException("action");
-
-            source.ForEachAsync(action).Wait();
-        }
-
-        public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource, int> action)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (action == null)
-                throw new ArgumentNullException("action");
-
-            return ForEachAsync(source, action, CancellationToken.None);
-        }
-
-        public static Task<double> Average(this IAsyncEnumerable<long> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Average(source, CancellationToken.None);
-        }
-
-        public static Task<double?> Average(this IAsyncEnumerable<long?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Average(source, CancellationToken.None);
-        }
-
-        public static Task<double> Average(this IAsyncEnumerable<double> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Average(source, CancellationToken.None);
-        }
-
-        public static Task<double?> Average(this IAsyncEnumerable<double?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Average(source, CancellationToken.None);
-        }
-
-        public static Task<float> Average(this IAsyncEnumerable<float> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Average(source, CancellationToken.None);
-        }
-
-        public static Task<float?> Average(this IAsyncEnumerable<float?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Average(source, CancellationToken.None);
-        }
-
-        public static Task<decimal> Average(this IAsyncEnumerable<decimal> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Average(source, CancellationToken.None);
-        }
-
-        public static Task<decimal?> Average(this IAsyncEnumerable<decimal?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Average(source, CancellationToken.None);
-        }
-
-        public static Task<double?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Average(source, selector, CancellationToken.None);
-        }
-
-        public static Task<double> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Average(source, selector, CancellationToken.None);
-        }
-
-        public static Task<double> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Average(source, selector, CancellationToken.None);
-        }
-
-        public static Task<double?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Average(source, selector, CancellationToken.None);
-        }
-
-        public static Task<double> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Average(source, selector, CancellationToken.None);
-        }
-
-        public static Task<double?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Average(source, selector, CancellationToken.None);
-        }
-
-        public static Task<float> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Average(source, selector, CancellationToken.None);
-        }
-
-        public static Task<float?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Average(source, selector, CancellationToken.None);
-        }
-
-        public static Task<decimal> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Average(source, selector, CancellationToken.None);
-        }
-
-        public static Task<decimal?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Average(source, selector, CancellationToken.None);
-        }
-
-        public static Task<int> Max(this IAsyncEnumerable<int> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Max(source, CancellationToken.None);
-        }
-
-        public static Task<long> Max(this IAsyncEnumerable<long> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Max(source, CancellationToken.None);
-        }
-
-        public static Task<double> Max(this IAsyncEnumerable<double> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Max(source, CancellationToken.None);
-        }
-
-        public static Task<float> Max(this IAsyncEnumerable<float> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Max(source, CancellationToken.None);
-        }
-
-        public static Task<decimal> Max(this IAsyncEnumerable<decimal> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Max(source, CancellationToken.None);
-        }
-
-        public static Task<int?> Max(this IAsyncEnumerable<int?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Max(source, CancellationToken.None);
-        }
-
-        public static Task<long?> Max(this IAsyncEnumerable<long?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Max(source, CancellationToken.None);
-        }
-
-        public static Task<double?> Max(this IAsyncEnumerable<double?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Max(source, CancellationToken.None);
-        }
-
-        public static Task<float?> Max(this IAsyncEnumerable<float?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Max(source, CancellationToken.None);
-        }
-
-        public static Task<decimal?> Max(this IAsyncEnumerable<decimal?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Max(source, CancellationToken.None);
-        }
-
-        public static Task<TSource> Max<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Max(source, CancellationToken.None);
-        }
-
-        public static Task<int> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Max(source, selector, CancellationToken.None);
-        }
-
-        public static Task<long> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Max(source, selector, CancellationToken.None);
-        }
-
-        public static Task<double> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Max(source, selector, CancellationToken.None);
-        }
-
-        public static Task<float> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Max(source, selector, CancellationToken.None);
-        }
-
-        public static Task<decimal> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Max(source, selector, CancellationToken.None);
-        }
-
-        public static Task<int?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Max(source, selector, CancellationToken.None);
-        }
-
-        public static Task<long?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Max(source, selector, CancellationToken.None);
-        }
-
-        public static Task<double?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Max(source, selector, CancellationToken.None);
-        }
-
-        public static Task<float?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Max(source, selector, CancellationToken.None);
-        }
-
-        public static Task<decimal?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Max(source, selector, CancellationToken.None);
-        }
-
-        public static Task<TResult> Max<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Max(source, selector, CancellationToken.None);
-        }
-
-        public static Task<int> Min(this IAsyncEnumerable<int> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Min(source, CancellationToken.None);
-        }
-
-        public static Task<long> Min(this IAsyncEnumerable<long> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Min(source, CancellationToken.None);
-        }
-
-        public static Task<double> Min(this IAsyncEnumerable<double> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Min(source, CancellationToken.None);
-        }
-
-        public static Task<float> Min(this IAsyncEnumerable<float> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Min(source, CancellationToken.None);
-        }
-
-        public static Task<decimal> Min(this IAsyncEnumerable<decimal> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Min(source, CancellationToken.None);
-        }
-
-        public static Task<int?> Min(this IAsyncEnumerable<int?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Min(source, CancellationToken.None);
-        }
-
-        public static Task<long?> Min(this IAsyncEnumerable<long?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Min(source, CancellationToken.None);
-        }
-
-        public static Task<double?> Min(this IAsyncEnumerable<double?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Min(source, CancellationToken.None);
-        }
-
-        public static Task<float?> Min(this IAsyncEnumerable<float?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Min(source, CancellationToken.None);
-        }
-
-        public static Task<decimal?> Min(this IAsyncEnumerable<decimal?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Min(source, CancellationToken.None);
-        }
-
-        public static Task<TSource> Min<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Min(source, CancellationToken.None);
-        }
-
-        public static Task<int> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Min(source, selector, CancellationToken.None);
-        }
-
-        public static Task<long> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Min(source, selector, CancellationToken.None);
-        }
-
-        public static Task<double> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Min(source, selector, CancellationToken.None);
-        }
-
-        public static Task<float> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Min(source, selector, CancellationToken.None);
-        }
-
-        public static Task<decimal> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Min(source, selector, CancellationToken.None);
-        }
-
-        public static Task<int?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Min(source, selector, CancellationToken.None);
-        }
-
-        public static Task<long?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Min(source, selector, CancellationToken.None);
-        }
-
-        public static Task<double?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Min(source, selector, CancellationToken.None);
-        }
-
-        public static Task<float?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (selector == null)
-                throw new ArgumentNullException("selector");
-
-            return Min(source, selector, CancellationToken.None);
-        }
-
-        public static Task<bool> SequenceEqual<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
-        {
-            if (first == null)
-                throw new ArgumentNullException("first");
-            if (second == null)
-                throw new ArgumentNullException("second");
-            if (comparer == null)
-                throw new ArgumentNullException("comparer");
-
-            return SequenceEqual(first, second, comparer, CancellationToken.None);
-        }
-
-        public static Task<bool> SequenceEqual<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
-        {
-            if (first == null)
-                throw new ArgumentNullException("first");
-            if (second == null)
-                throw new ArgumentNullException("second");
-
-            return SequenceEqual(first, second, CancellationToken.None);
-        }
-
-        public static Task<TResult> Aggregate<TSource, TAccumulate, TResult>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (accumulator == null)
-                throw new ArgumentNullException("accumulator");
-            if (resultSelector == null)
-                throw new ArgumentNullException("resultSelector");
-
-            return Aggregate(source, seed, accumulator, resultSelector, CancellationToken.None);
-        }
-
-        public static Task<TAccumulate> Aggregate<TSource, TAccumulate>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (accumulator == null)
-                throw new ArgumentNullException("accumulator");
-
-            return Aggregate(source, seed, accumulator, CancellationToken.None);
-        }
-
-        public static Task<TSource> Aggregate<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (accumulator == null)
-                throw new ArgumentNullException("accumulator");
-
-            return Aggregate(source, accumulator, CancellationToken.None);
-        }
-
-        public static Task<int> Count<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Count(source, CancellationToken.None);
-        }
-
-        public static Task<int> Count<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (predicate == null)
-                throw new ArgumentNullException("predicate");
-
-            return Count(source, predicate, CancellationToken.None);
-        }
-
-        public static Task<long> LongCount<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return LongCount(source, CancellationToken.None);
-        }
-
-        public static Task<long> LongCount<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (predicate == null)
-                throw new ArgumentNullException("predicate");
-
-            return LongCount(source, predicate, CancellationToken.None);
-        }
-
-        public static Task<bool> All<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (predicate == null)
-                throw new ArgumentNullException("predicate");
-
-            return All(source, predicate, CancellationToken.None);
-        }
-
-        public static Task<bool> Any<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (predicate == null)
-                throw new ArgumentNullException("predicate");
-
-            return Any(source, predicate, CancellationToken.None);
-        }
-
-        public static Task<bool> Any<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Any(source, CancellationToken.None);
-        }
-
-        public static Task<bool> Contains<TSource>(this IAsyncEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (comparer == null)
-                throw new ArgumentNullException("comparer");
-
-            return Contains(source, value, comparer, CancellationToken.None);
-        }
-
-        public static Task<bool> Contains<TSource>(this IAsyncEnumerable<TSource> source, TSource value)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Contains(source, value, CancellationToken.None);
-        }
-
-        public static Task<TSource> First<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return First(source, CancellationToken.None);
-        }
-
-        public static Task<TSource> First<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (predicate == null)
-                throw new ArgumentNullException("predicate");
-
-            return First(source, predicate, CancellationToken.None);
-        }
-
-        public static Task<TSource> FirstOrDefault<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return FirstOrDefault(source, CancellationToken.None);
-        }
-
-        public static Task<TSource> FirstOrDefault<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (predicate == null)
-                throw new ArgumentNullException("predicate");
-
-            return FirstOrDefault(source, predicate, CancellationToken.None);
-        }
-
-        public static Task<TSource> Last<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Last(source, CancellationToken.None);
-        }
-
-        public static Task<TSource> Last<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (predicate == null)
-                throw new ArgumentNullException("predicate");
-
-            return Last(source, predicate, CancellationToken.None);
-        }
-
-        public static Task<TSource> LastOrDefault<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return LastOrDefault(source, CancellationToken.None);
-        }
-
-        public static Task<TSource> LastOrDefault<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (predicate == null)
-                throw new ArgumentNullException("predicate");
-
-            return LastOrDefault(source, predicate, CancellationToken.None);
-        }
-
-        public static Task<TSource> Single<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Single(source, CancellationToken.None);
-        }
-
-        public static Task<TSource> Single<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (predicate == null)
-                throw new ArgumentNullException("predicate");
-
-            return Single(source, predicate, CancellationToken.None);
-        }
-
-        public static Task<TSource> SingleOrDefault<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return SingleOrDefault(source, CancellationToken.None);
-        }
-
-        public static Task<TSource> SingleOrDefault<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (predicate == null)
-                throw new ArgumentNullException("predicate");
-
-            return SingleOrDefault(source, predicate, CancellationToken.None);
-        }
-
-        public static Task<TSource> ElementAt<TSource>(this IAsyncEnumerable<TSource> source, int index)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return ElementAt(source, index, CancellationToken.None);
-        }
-
-        public static Task<TSource> ElementAtOrDefault<TSource>(this IAsyncEnumerable<TSource> source, int index)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return ElementAtOrDefault(source, index, CancellationToken.None);
-        }
-
-        public static Task<TSource[]> ToArray<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return ToArray(source, CancellationToken.None);
-        }
-
-        public static Task<List<TSource>> ToList<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return ToList(source, CancellationToken.None);
-        }
-
-        public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (keySelector == null)
-                throw new ArgumentNullException("keySelector");
-            if (elementSelector == null)
-                throw new ArgumentNullException("elementSelector");
-            if (comparer == null)
-                throw new ArgumentNullException("comparer");
-
-            return ToDictionary(source, keySelector, elementSelector, comparer, CancellationToken.None);
-        }
-
-        public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (keySelector == null)
-                throw new ArgumentNullException("keySelector");
-            if (elementSelector == null)
-                throw new ArgumentNullException("elementSelector");
-
-            return ToDictionary(source, keySelector, elementSelector, CancellationToken.None);
-        }
-
-        public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (keySelector == null)
-                throw new ArgumentNullException("keySelector");
-            if (comparer == null)
-                throw new ArgumentNullException("comparer");
-
-            return ToDictionary(source, keySelector, comparer, CancellationToken.None);
-        }
-
-        public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (keySelector == null)
-                throw new ArgumentNullException("keySelector");
-
-            return ToDictionary(source, keySelector, CancellationToken.None);
-        }
-
-        public static Task<ILookup<TKey, TElement>> ToLookup<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (keySelector == null)
-                throw new ArgumentNullException("keySelector");
-            if (elementSelector == null)
-                throw new ArgumentNullException("elementSelector");
-            if (comparer == null)
-                throw new ArgumentNullException("comparer");
-
-            return ToLookup(source, keySelector, elementSelector, comparer, CancellationToken.None);
-        }
-
-        public static Task<ILookup<TKey, TElement>> ToLookup<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (keySelector == null)
-                throw new ArgumentNullException("keySelector");
-            if (elementSelector == null)
-                throw new ArgumentNullException("elementSelector");
-
-            return ToLookup(source, keySelector, elementSelector, CancellationToken.None);
-        }
-
-        public static Task<ILookup<TKey, TSource>> ToLookup<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (keySelector == null)
-                throw new ArgumentNullException("keySelector");
-            if (comparer == null)
-                throw new ArgumentNullException("comparer");
-
-            return ToLookup(source, keySelector, comparer, CancellationToken.None);
-        }
-
-        public static Task<ILookup<TKey, TSource>> ToLookup<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (keySelector == null)
-                throw new ArgumentNullException("keySelector");
-
-            return ToLookup(source, keySelector, CancellationToken.None);
-        }
-
-        public static Task<double> Average(this IAsyncEnumerable<int> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Average(source, CancellationToken.None);
-        }
-
-        public static Task<double?> Average(this IAsyncEnumerable<int?> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return Average(source, CancellationToken.None);
-        }
-
-        public static Task<bool> IsEmpty<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-
-            return source.IsEmpty(CancellationToken.None);
-        }
-
-        public static Task<TSource> Min<TSource>(this IAsyncEnumerable<TSource> source, IComparer<TSource> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (comparer == null)
-                throw new ArgumentNullException("comparer");
-
-            return source.Min(comparer, CancellationToken.None);
-        }
-
-        public static Task<IList<TSource>> MinBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (keySelector == null)
-                throw new ArgumentNullException("keySelector");
-
-            return source.MinBy(keySelector, CancellationToken.None);
-        }
-
-        public static Task<IList<TSource>> MinBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (keySelector == null)
-                throw new ArgumentNullException("keySelector");
-            if (comparer == null)
-                throw new ArgumentNullException("comparer");
-
-            return source.MinBy(keySelector, comparer, CancellationToken.None);
-        }
-
-        public static Task<TSource> Max<TSource>(this IAsyncEnumerable<TSource> source, IComparer<TSource> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (comparer == null)
-                throw new ArgumentNullException("comparer");
-
-            return source.Max(comparer, CancellationToken.None);
-        }
-
-        public static Task<IList<TSource>> MaxBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (keySelector == null)
-                throw new ArgumentNullException("keySelector");
-
-            return source.MaxBy(keySelector, CancellationToken.None);
-        }
-
-        public static Task<IList<TSource>> MaxBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException("source");
-            if (keySelector == null)
-                throw new ArgumentNullException("keySelector");
-            if (comparer == null)
-                throw new ArgumentNullException("comparer");
-
-            return source.MaxBy(keySelector, comparer, CancellationToken.None);
-        }
-    }
-}

+ 0 - 648
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Multiple.cs

@@ -1,648 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Threading;
-
-namespace System.Linq
-{
-    public static partial class AsyncEnumerable
-    {
-        public static IAsyncEnumerable<TSource> Concat<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-
-            return Create(() =>
-            {
-                var switched = false;
-                var e = first.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var a = new AssignableDisposable { Disposable = e };
-                var d = Disposable.Create(cts, a);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        return true;
-                    }
-                    if (switched)
-                    {
-                        return false;
-                    }
-                    switched = true;
-
-                    e = second.GetEnumerator();
-                    a.Disposable = e;
-
-                    return await f(ct).ConfigureAwait(false);
-                };
-
-                return Create(
-                    f,
-                    () => e.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IAsyncEnumerable<TFirst> first, IAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> selector)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return Create(() =>
-            {
-                var e1 = first.GetEnumerator();
-                var e2 = second.GetEnumerator();
-                var current = default(TResult);
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e1, e2);
-
-                return Create(
-                    ct => e1.MoveNext(cts.Token).Zip(e2.MoveNext(cts.Token), (f, s) =>
-                        {
-                            var result = f && s;
-                            if (result)
-                                current = selector(e1.Current, e2.Current);
-                            return result;
-                        }),
-                    () => current,
-                    d.Dispose
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Except<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return Create(() =>
-            {
-                var e = first.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var mapTask = default(Task<Dictionary<TSource, TSource>>);
-                var getMapTask = new Func<CancellationToken, Task<Dictionary<TSource, TSource>>>(ct =>
-                    mapTask ?? (mapTask = second.ToDictionary(x => x, comparer, ct)));
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (await e.MoveNext(ct).Zip(getMapTask(ct), (b, _) => b).ConfigureAwait(false))
-                    {
-                        if (!mapTask.Result.ContainsKey(e.Current))
-                            return true;
-                        return await f(ct).ConfigureAwait(false);
-                    }
-                    return false;
-                };
-
-                return Create(
-                    f,
-                    () => e.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Except<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-
-            return first.Except(second, EqualityComparer<TSource>.Default);
-        }
-
-        public static IAsyncEnumerable<TSource> Intersect<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return Create(() =>
-            {
-                var e = first.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var mapTask = default(Task<Dictionary<TSource, TSource>>);
-                var getMapTask = new Func<CancellationToken, Task<Dictionary<TSource, TSource>>>(ct =>
-                {
-                    if (mapTask == null)
-                        mapTask = second.ToDictionary(x => x, comparer, ct);
-                    return mapTask;
-                });
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (await e.MoveNext(ct).Zip(getMapTask(ct), (b, _) => b).ConfigureAwait(false))
-                    {
-                        if (mapTask.Result.ContainsKey(e.Current))
-                            return true;
-                        return await f(ct).ConfigureAwait(false);
-                    }
-                    return false;
-                };
-
-                return Create(
-                    f,
-                    () => e.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Intersect<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-
-            return first.Intersect(second, EqualityComparer<TSource>.Default);
-        }
-
-        public static IAsyncEnumerable<TSource> Union<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return first.Concat(second).Distinct(comparer);
-        }
-
-        public static IAsyncEnumerable<TSource> Union<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-
-            return first.Union(second, EqualityComparer<TSource>.Default);
-        }
-
-        public static Task<bool> SequenceEqual<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return SequenceEqual_(first, second, comparer, cancellationToken);
-        }
-
-        private static async Task<bool> SequenceEqual_<TSource>(IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer,
-            CancellationToken cancellationToken)
-        {
-            using (var e1 = first.GetEnumerator())
-            using (var e2 = second.GetEnumerator())
-            {
-                while (await e1.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    if (!(await e2.MoveNext(cancellationToken).ConfigureAwait(false) && comparer.Equals(e1.Current, e2.Current)))
-                    {
-                        return false;
-                    }
-                }
-
-                return !await e2.MoveNext(cancellationToken).ConfigureAwait(false);
-            }
-        }
-
-        public static Task<bool> SequenceEqual<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, CancellationToken cancellationToken)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-
-            return first.SequenceEqual(second, EqualityComparer<TSource>.Default, cancellationToken);
-        }
-
-        public static IAsyncEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IAsyncEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
-        {
-            if (outer == null)
-                throw new ArgumentNullException(nameof(outer));
-            if (inner == null)
-                throw new ArgumentNullException(nameof(inner));
-            if (outerKeySelector == null)
-                throw new ArgumentNullException(nameof(outerKeySelector));
-            if (innerKeySelector == null)
-                throw new ArgumentNullException(nameof(innerKeySelector));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-
-            return new GroupJoinAsyncEnumerable<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
-        }
-
-        public static IAsyncEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IAsyncEnumerable<TInner>, TResult> resultSelector)
-        {
-            if (outer == null)
-                throw new ArgumentNullException(nameof(outer));
-            if (inner == null)
-                throw new ArgumentNullException(nameof(inner));
-            if (outerKeySelector == null)
-                throw new ArgumentNullException(nameof(outerKeySelector));
-            if (innerKeySelector == null)
-                throw new ArgumentNullException(nameof(innerKeySelector));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-
-            return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
-        }
-
-
-        private sealed class GroupJoinAsyncEnumerable<TOuter, TInner, TKey, TResult> : IAsyncEnumerable<TResult>
-        {
-            private readonly IAsyncEnumerable<TOuter> _outer;
-            private readonly IAsyncEnumerable<TInner> _inner;
-            private readonly Func<TOuter, TKey> _outerKeySelector;
-            private readonly Func<TInner, TKey> _innerKeySelector;
-            private readonly Func<TOuter, IAsyncEnumerable<TInner>, TResult> _resultSelector;
-            private readonly IEqualityComparer<TKey> _comparer;
-
-            public GroupJoinAsyncEnumerable(
-                IAsyncEnumerable<TOuter> outer,
-                IAsyncEnumerable<TInner> inner,
-                Func<TOuter, TKey> outerKeySelector,
-                Func<TInner, TKey> innerKeySelector,
-                Func<TOuter, IAsyncEnumerable<TInner>, TResult> resultSelector,
-                IEqualityComparer<TKey> comparer)
-            {
-                _outer = outer;
-                _inner = inner;
-                _outerKeySelector = outerKeySelector;
-                _innerKeySelector = innerKeySelector;
-                _resultSelector = resultSelector;
-                _comparer = comparer;
-            }
-
-            public IAsyncEnumerator<TResult> GetEnumerator()
-                => new GroupJoinAsyncEnumerator(
-                    _outer.GetEnumerator(),
-                    _inner,
-                    _outerKeySelector,
-                    _innerKeySelector,
-                    _resultSelector,
-                    _comparer);
-
-            private sealed class GroupJoinAsyncEnumerator : IAsyncEnumerator<TResult>
-            {
-                private readonly IAsyncEnumerator<TOuter> _outer;
-                private readonly IAsyncEnumerable<TInner> _inner;
-                private readonly Func<TOuter, TKey> _outerKeySelector;
-                private readonly Func<TInner, TKey> _innerKeySelector;
-                private readonly Func<TOuter, IAsyncEnumerable<TInner>, TResult> _resultSelector;
-                private readonly IEqualityComparer<TKey> _comparer;
-
-                private Internal.Lookup<TKey, TInner> _lookup;
-
-                public GroupJoinAsyncEnumerator(
-                    IAsyncEnumerator<TOuter> outer,
-                    IAsyncEnumerable<TInner> inner,
-                    Func<TOuter, TKey> outerKeySelector,
-                    Func<TInner, TKey> innerKeySelector,
-                    Func<TOuter, IAsyncEnumerable<TInner>, TResult> resultSelector,
-                    IEqualityComparer<TKey> comparer)
-                {
-                    _outer = outer;
-                    _inner = inner;
-                    _outerKeySelector = outerKeySelector;
-                    _innerKeySelector = innerKeySelector;
-                    _resultSelector = resultSelector;
-                    _comparer = comparer;
-                }
-
-                public async Task<bool> MoveNext(CancellationToken cancellationToken)
-                {
-                    // nothing to do 
-                    if (!await _outer.MoveNext(cancellationToken).ConfigureAwait(false))
-                    {
-                        return false;
-                    }
-
-                    if (_lookup == null)
-                    {
-                        _lookup = await Internal.Lookup<TKey, TInner>.CreateForJoinAsync(_inner, _innerKeySelector, _comparer, cancellationToken).ConfigureAwait(false);
-                    }
-                    
-                    var item = _outer.Current;
-                    Current = _resultSelector(item, new AsyncEnumerableAdapter<TInner>(_lookup[_outerKeySelector(item)]));
-                    return true;
-                }
-
-                public TResult Current { get; private set; }
-
-                public void Dispose()
-                {
-                    _outer.Dispose();
-                }
-
-      
-            }
-        }
-
-        private sealed class AsyncEnumerableAdapter<T> : IAsyncEnumerable<T>
-        {
-            private readonly IEnumerable<T> _source;
-
-            public AsyncEnumerableAdapter(IEnumerable<T> source)
-            {
-                _source = source;
-            }
-
-            public IAsyncEnumerator<T> GetEnumerator()
-                => new AsyncEnumeratorAdapter(_source.GetEnumerator());
-
-            private sealed class AsyncEnumeratorAdapter : IAsyncEnumerator<T>
-            {
-                private readonly IEnumerator<T> _enumerator;
-
-                public AsyncEnumeratorAdapter(IEnumerator<T> enumerator)
-                {
-                    _enumerator = enumerator;
-                }
-
-                public Task<bool> MoveNext(CancellationToken cancellationToken)
-                {
-                    cancellationToken.ThrowIfCancellationRequested();
-
-#if HAS_AWAIT
-                    return Task.FromResult(_enumerator.MoveNext());
-#else
-                    return TaskEx.FromResult(_enumerator.MoveNext());
-#endif
-                }
-
-                public T Current => _enumerator.Current;
-
-                public void Dispose() => _enumerator.Dispose();
-            }
-        }
-
-        public static IAsyncEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
-        {
-            if (outer == null)
-                throw new ArgumentNullException(nameof(outer));
-            if (inner == null)
-                throw new ArgumentNullException(nameof(inner));
-            if (outerKeySelector == null)
-                throw new ArgumentNullException(nameof(outerKeySelector));
-            if (innerKeySelector == null)
-                throw new ArgumentNullException(nameof(innerKeySelector));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return Create(() =>
-            {
-                var oe = outer.GetEnumerator();
-                var ie = inner.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, oe, ie);
-
-                var current = default(TResult);
-                var useOuter = true;
-                var outerMap = new Dictionary<TKey, List<TOuter>>(comparer);
-                var innerMap = new Dictionary<TKey, List<TInner>>(comparer);
-                var q = new Queue<TResult>();
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (q.Count > 0)
-                    {
-                        current = q.Dequeue();
-                        return true;
-                    }
-
-                    var b = useOuter;
-                    if (ie == null && oe == null)
-                    {
-                        return false;
-                    }
-                    if (ie == null)
-                        b = true;
-                    else if (oe == null)
-                        b = false;
-                    useOuter = !useOuter;
-
-                    var enqueue = new Func<TOuter, TInner, bool>((o, i) =>
-                    {
-                        var result = resultSelector(o, i);
-                        q.Enqueue(result);
-                        return true;
-                    });
-
-                    if (b)
-                    {
-                        if (await oe.MoveNext(ct).ConfigureAwait(false))
-                        {
-                            var element = oe.Current;
-                            var key = default(TKey);
-
-                            key = outerKeySelector(element);
-
-                            var outerList = default(List<TOuter>);
-                            if (!outerMap.TryGetValue(key, out outerList))
-                            {
-                                outerList = new List<TOuter>();
-                                outerMap.Add(key, outerList);
-                            }
-
-                            outerList.Add(element);
-
-                            var innerList = default(List<TInner>);
-                            if (!innerMap.TryGetValue(key, out innerList))
-                            {
-                                innerList = new List<TInner>();
-                                innerMap.Add(key, innerList);
-                            }
-
-                            foreach (var v in innerList)
-                            {
-                                if (!enqueue(element, v))
-                                    return false;
-                            }
-
-                            return await f(ct).ConfigureAwait(false);
-                        }
-                        oe.Dispose();
-                        oe = null;
-                        return await f(ct).ConfigureAwait(false);
-                    }
-                    if (await ie.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        var element = ie.Current;
-                        var key = innerKeySelector(element);
-
-                        var innerList = default(List<TInner>);
-                        if (!innerMap.TryGetValue(key, out innerList))
-                        {
-                            innerList = new List<TInner>();
-                            innerMap.Add(key, innerList);
-                        }
-
-                        innerList.Add(element);
-
-                        var outerList = default(List<TOuter>);
-                        if (!outerMap.TryGetValue(key, out outerList))
-                        {
-                            outerList = new List<TOuter>();
-                            outerMap.Add(key, outerList);
-                        }
-
-                        foreach (var v in outerList)
-                        {
-                            if (!enqueue(v, element))
-                                return false;
-                        }
-
-                        return await f(ct).ConfigureAwait(false);
-                    }
-                    ie.Dispose();
-                    ie = null;
-                    return await f(ct).ConfigureAwait(false);
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    ie
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector)
-        {
-            if (outer == null)
-                throw new ArgumentNullException(nameof(outer));
-            if (inner == null)
-                throw new ArgumentNullException(nameof(inner));
-            if (outerKeySelector == null)
-                throw new ArgumentNullException(nameof(outerKeySelector));
-            if (innerKeySelector == null)
-                throw new ArgumentNullException(nameof(innerKeySelector));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-
-            return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
-        }
-
-        public static IAsyncEnumerable<TSource> Concat<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
-        {
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return sources.Concat_();
-        }
-
-        public static IAsyncEnumerable<TSource> Concat<TSource>(params IAsyncEnumerable<TSource>[] sources)
-        {
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return sources.Concat_();
-        }
-
-        private static IAsyncEnumerable<TSource> Concat_<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
-        {
-            return Create(() =>
-            {
-                var se = sources.GetEnumerator();
-                var e = default(IAsyncEnumerator<TSource>);
-
-                var cts = new CancellationTokenDisposable();
-                var a = new AssignableDisposable();
-                var d = Disposable.Create(cts, se, a);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (e == null)
-                    {
-                        var b = false;
-                        b = se.MoveNext();
-                        if (b)
-                            e = se.Current.GetEnumerator();
-
-                        if (!b)
-                        {
-                            return false;
-                        }
-
-                        a.Disposable = e;
-                    }
-
-                    if (await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        return true;
-                    }
-                    e.Dispose();
-                    e = null;
-
-                    return await f(ct).ConfigureAwait(false);
-                };
-
-                return Create(
-                    f,
-                    () => e.Current,
-                    d.Dispose,
-                    a
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TOther> SelectMany<TSource, TOther>(this IAsyncEnumerable<TSource> source, IAsyncEnumerable<TOther> other)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (other == null)
-                throw new ArgumentNullException(nameof(other));
-
-            return source.SelectMany(_ => other);
-        }
-    }
-}

+ 0 - 1882
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.Single.cs

@@ -1,1882 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-using System.Runtime.ExceptionServices;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace System.Linq
-{
-    public static partial class AsyncEnumerable
-    {
-        public static IAsyncEnumerable<TResult> Select<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-                var current = default(TResult);
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                return Create(
-                    async ct =>
-                    {
-                        if (await e.MoveNext(cts.Token).ConfigureAwait(false))
-                        {
-                            current = selector(e.Current);
-                            return true;
-                        }
-                        return false;
-                    },
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TResult> Select<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, int, TResult> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-                var current = default(TResult);
-                var index = 0;
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                return Create(
-                    async ct =>
-                    {
-                        if (await e.MoveNext(cts.Token).ConfigureAwait(false))
-                        {
-                            current = selector(e.Current, checked(index++));
-                            return true;
-                        }
-                        return false;
-                    },
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> AsAsyncEnumerable<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Select(x => x);
-        }
-
-        public static IAsyncEnumerable<TSource> Where<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        if (predicate(e.Current))
-                            return true;
-                        return await f(ct).ConfigureAwait(false);
-                    }
-                    return false;
-                };
-
-                return Create(
-                    ct => f(cts.Token),
-                    () => e.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Where<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-                var index = 0;
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        if (predicate(e.Current, checked(index++)))
-                            return true;
-                        return await f(ct).ConfigureAwait(false);
-                    }
-                    return false;
-                };
-
-                return Create(
-                    ct => f(cts.Token),
-                    () => e.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TResult> SelectMany<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, IAsyncEnumerable<TResult>> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-                var ie = default(IAsyncEnumerator<TResult>);
-
-                var innerDisposable = new AssignableDisposable();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, innerDisposable, e);
-
-                var inner = default(Func<CancellationToken, Task<bool>>);
-                var outer = default(Func<CancellationToken, Task<bool>>);
-
-                inner = async ct =>
-                {
-                    if (await ie.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        return true;
-                    }
-                    innerDisposable.Disposable = null;
-                    return await outer(ct).ConfigureAwait(false);
-                };
-
-                outer = async ct =>
-                {
-                    if (await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        var enumerable = selector(e.Current);
-                        ie = enumerable.GetEnumerator();
-                        innerDisposable.Disposable = ie;
-
-                        return await inner(ct).ConfigureAwait(false);
-                    }
-                    return false;
-                };
-
-                return Create(ct => ie == null ? outer(cts.Token) : inner(cts.Token),
-                    () => ie.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TResult> SelectMany<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, int, IAsyncEnumerable<TResult>> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-                var ie = default(IAsyncEnumerator<TResult>);
-
-                var index = 0;
-
-                var innerDisposable = new AssignableDisposable();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, innerDisposable, e);
-
-                var inner = default(Func<CancellationToken, Task<bool>>);
-                var outer = default(Func<CancellationToken, Task<bool>>);
-
-                inner = async ct =>
-                {
-                    if (await ie.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        return true;
-                    }
-                    innerDisposable.Disposable = null;
-                    return await outer(ct).ConfigureAwait(false);
-                };
-
-                outer = async ct =>
-                {
-                    if (await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        var enumerable = selector(e.Current, checked(index++));
-                        ie = enumerable.GetEnumerator();
-                        innerDisposable.Disposable = ie;
-
-                        return await inner(ct).ConfigureAwait(false);
-                    }
-                    return false;
-                };
-
-                return Create(ct => ie == null ? outer(cts.Token) : inner(cts.Token),
-                    () => ie.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, IAsyncEnumerable<TCollection>> selector, Func<TSource, TCollection, TResult> resultSelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-
-            return source.SelectMany(x => selector(x).Select(y => resultSelector(x, y)));
-        }
-
-        public static IAsyncEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, int, IAsyncEnumerable<TCollection>> selector, Func<TSource, TCollection, TResult> resultSelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-
-            return source.SelectMany((x, i) => selector(x, i).Select(y => resultSelector(x, y)));
-        }
-
-        public static IAsyncEnumerable<TType> OfType<TType>(this IAsyncEnumerable<object> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Where(x => x is TType).Cast<TType>();
-        }
-
-        public static IAsyncEnumerable<TResult> Cast<TResult>(this IAsyncEnumerable<object> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Select(x => (TResult)x);
-        }
-
-        public static IAsyncEnumerable<TSource> Take<TSource>(this IAsyncEnumerable<TSource> source, int count)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (count < 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-                var n = count;
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                return Create(
-                    async ct =>
-                    {
-                        if (n == 0)
-                            return false;
-
-                        var result = await e.MoveNext(cts.Token).ConfigureAwait(false);
-
-                        --n;
-
-                        if (n == 0)
-                            e.Dispose();
-
-                        return result;
-                    },
-                    () => e.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> TakeWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                return Create(
-                    async ct =>
-                    {
-                        if (await e.MoveNext(cts.Token).ConfigureAwait(false))
-                        {
-                            return predicate(e.Current);
-                        }
-                        return false;
-                    },
-                    () => e.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> TakeWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-                var index = 0;
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                return Create(
-                    async ct =>
-                    {
-                        if (await e.MoveNext(cts.Token).ConfigureAwait(false))
-                        {
-                            return predicate(e.Current, checked(index++));
-                        }
-                        return false;
-                    },
-                    () => e.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Skip<TSource>(this IAsyncEnumerable<TSource> source, int count)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (count < 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-                var n = count;
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    var moveNext = await e.MoveNext(ct).ConfigureAwait(false);
-                    if (n == 0)
-                    {
-                        return moveNext;
-                    }
-                    --n;
-                    if (!moveNext)
-                    {
-                        return false;
-                    }
-                    return await f(ct).ConfigureAwait(false);
-                };
-
-                return Create(
-                    ct => f(cts.Token),
-                    () => e.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-                var skipping = true;
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (skipping)
-                    {
-                        if (await e.MoveNext(ct).ConfigureAwait(false))
-                        {
-                            if (predicate(e.Current))
-                                return await f(ct).ConfigureAwait(false);
-                            skipping = false;
-                            return true;
-                        }
-                        return false;
-                    }
-                    return await e.MoveNext(ct).ConfigureAwait(false);
-                };
-
-                return Create(
-                    f,
-                    () => e.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (predicate == null)
-                throw new ArgumentNullException(nameof(predicate));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-                var skipping = true;
-                var index = 0;
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (skipping)
-                    {
-                        if (await e.MoveNext(ct).ConfigureAwait(false))
-                        {
-                            if (predicate(e.Current, checked(index++)))
-                                return await f(ct).ConfigureAwait(false);
-                            skipping = false;
-                            return true;
-                        }
-                        return false;
-                    }
-                    return await e.MoveNext(ct).ConfigureAwait(false);
-                };
-
-                return Create(
-                    f,
-                    () => e.Current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> DefaultIfEmpty<TSource>(this IAsyncEnumerable<TSource> source, TSource defaultValue)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Create(() =>
-            {
-                var done = false;
-                var hasElements = false;
-                var e = source.GetEnumerator();
-                var current = default(TSource);
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (done)
-                        return false;
-                    if (await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        hasElements = true;
-                        current = e.Current;
-                        return true;
-                    }
-                    done = true;
-                    if (!hasElements)
-                    {
-                        current = defaultValue;
-                        return true;
-                    }
-                    return false;
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> DefaultIfEmpty<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.DefaultIfEmpty(default(TSource));
-        }
-
-        public static IAsyncEnumerable<TSource> Distinct<TSource>(this IAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return Defer(() =>
-            {
-                var set = new HashSet<TSource>(comparer);
-                return source.Where(set.Add);
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Distinct<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Distinct(EqualityComparer<TSource>.Default);
-        }
-
-        public static IAsyncEnumerable<TSource> Reverse<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-                var stack = default(Stack<TSource>);
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                return Create(
-                    async ct =>
-                    {
-                        if (stack == null)
-                        {
-                            stack = await Create(() => e).Aggregate(new Stack<TSource>(), (s, x) => { s.Push(x); return s; }, cts.Token).ConfigureAwait(false);
-                            return stack.Count > 0;
-                        }
-                        stack.Pop();
-                        return stack.Count > 0;
-                    },
-                    () => stack.Peek(),
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IOrderedAsyncEnumerable<TSource> OrderBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return new OrderedAsyncEnumerable<TSource, TKey>(
-                Create(() =>
-                {
-                    var current = default(IEnumerable<TSource>);
-
-                    return Create(
-                        async ct =>
-                        {
-                            if (current == null)
-                            {
-                                current = await source.ToList(ct).ConfigureAwait(false);
-                                return true;
-                            }
-                            return false;
-                        },
-                        () => current,
-                        () => { }
-                    );
-                }),
-                keySelector,
-                comparer
-            );
-        }
-
-        public static IOrderedAsyncEnumerable<TSource> OrderBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return source.OrderBy(keySelector, Comparer<TKey>.Default);
-        }
-
-        public static IOrderedAsyncEnumerable<TSource> OrderByDescending<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.OrderBy(keySelector, new ReverseComparer<TKey>(comparer));
-        }
-
-        public static IOrderedAsyncEnumerable<TSource> OrderByDescending<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return source.OrderByDescending(keySelector, Comparer<TKey>.Default);
-        }
-
-        public static IOrderedAsyncEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return source.ThenBy(keySelector, Comparer<TKey>.Default);
-        }
-
-        public static IOrderedAsyncEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.CreateOrderedEnumerable(keySelector, comparer, false);
-        }
-
-        public static IOrderedAsyncEnumerable<TSource> ThenByDescending<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return source.ThenByDescending(keySelector, Comparer<TKey>.Default);
-        }
-
-        public static IOrderedAsyncEnumerable<TSource> ThenByDescending<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.CreateOrderedEnumerable(keySelector, comparer, true);
-        }
-
-        static IEnumerable<IGrouping<TKey, TElement>> GroupUntil<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IComparer<TKey> comparer)
-        {
-            var group = default(EnumerableGrouping<TKey, TElement>);
-            foreach (var x in source)
-            {
-                var key = keySelector(x);
-                if (group == null || comparer.Compare(group.Key, key) != 0)
-                {
-                    group = new EnumerableGrouping<TKey, TElement>(key);
-                    yield return group;
-                }
-                group.Add(elementSelector(x));
-            }
-        }
-
-        class OrderedAsyncEnumerable<T, K> : IOrderedAsyncEnumerable<T>
-        {
-            private readonly IAsyncEnumerable<IEnumerable<T>> equivalenceClasses;
-            private readonly Func<T, K> keySelector;
-            private readonly IComparer<K> comparer;
-
-            public OrderedAsyncEnumerable(IAsyncEnumerable<IEnumerable<T>> equivalenceClasses, Func<T, K> keySelector, IComparer<K> comparer)
-            {
-                this.equivalenceClasses = equivalenceClasses;
-                this.keySelector = keySelector;
-                this.comparer = comparer;
-            }
-
-            public IOrderedAsyncEnumerable<T> CreateOrderedEnumerable<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer, bool descending)
-            {
-                if (descending)
-                    comparer = new ReverseComparer<TKey>(comparer);
-
-                return new OrderedAsyncEnumerable<T, TKey>(Classes(), keySelector, comparer);
-            }
-
-            IAsyncEnumerable<IEnumerable<T>> Classes()
-            {
-                return Create(() =>
-                {
-                    var e = equivalenceClasses.GetEnumerator();
-                    var list = new List<IEnumerable<T>>();
-                    var e1 = default(IEnumerator<IEnumerable<T>>);
-
-                    var cts = new CancellationTokenDisposable();
-                    var d1 = new AssignableDisposable();
-                    var d = Disposable.Create(cts, e, d1);
-
-                    var f = default(Func<CancellationToken, Task<bool>>);
-
-                    f = async ct =>
-                    {
-                        if (await e.MoveNext(ct).ConfigureAwait(false))
-                        {
-                            list.AddRange(e.Current.OrderBy(keySelector, comparer).GroupUntil(keySelector, x => x, comparer));
-                            return await f(ct).ConfigureAwait(false);
-                        }
-                        e.Dispose();
-
-                        e1 = list.GetEnumerator();
-                        d1.Disposable = e1;
-
-                        return e1.MoveNext();
-                    };
-
-                    return Create(
-                        async ct =>
-                        {
-                            if (e1 != null)
-                            {
-                                return e1.MoveNext();
-                            }
-                            return await f(cts.Token).ConfigureAwait(false);
-                        },
-                        () => e1.Current,
-                        d.Dispose,
-                        e
-                    );
-                });
-            }
-
-            public IAsyncEnumerator<T> GetEnumerator()
-            {
-                return Classes().SelectMany(x => x.ToAsyncEnumerable()).GetEnumerator();
-            }
-        }
-
-        class ReverseComparer<T> : IComparer<T>
-        {
-            IComparer<T> comparer;
-
-            public ReverseComparer(IComparer<T> comparer)
-            {
-                this.comparer = comparer;
-            }
-
-            public int Compare(T x, T y)
-            {
-                return -comparer.Compare(x, y);
-            }
-        }
-
-        public static IAsyncEnumerable<IAsyncGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (elementSelector == null)
-                throw new ArgumentNullException(nameof(elementSelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return Create(() =>
-            {
-                var gate = new object();
-
-                var e = source.GetEnumerator();
-                var count = 1;
-
-                var map = new Dictionary<TKey, Grouping<TKey, TElement>>(comparer);
-                var list = new List<IAsyncGrouping<TKey, TElement>>();
-
-                var index = 0;
-
-                var current = default(IAsyncGrouping<TKey, TElement>);
-                var faulted = default(ExceptionDispatchInfo);
-
-                var res = default(bool?);
-
-                var cts = new CancellationTokenDisposable();
-                var refCount = new Disposable(
-                    () =>
-                    {
-                        if (Interlocked.Decrement(ref count) == 0)
-                            e.Dispose();
-                    }
-                );
-                var d = Disposable.Create(cts, refCount);
-
-                var iterateSource = default(Func<CancellationToken, Task<bool>>);
-                iterateSource = async ct =>
-                {
-                    lock (gate)
-                    {
-                        if (res != null)
-                        {
-                            return res.Value;
-                        }
-                        res = null;
-                    }
-
-                    faulted?.Throw();
-
-                    try
-                    {
-                        res = await e.MoveNext(ct).ConfigureAwait(false);
-                        if (res == true)
-                        {
-                            var key = default(TKey);
-                            var element = default(TElement);
-
-                            var cur = e.Current;
-                            try
-                            {
-                                key = keySelector(cur);
-                                element = elementSelector(cur);
-                            }
-                            catch (Exception exception)
-                            {
-                                foreach (var v in map.Values)
-                                    v.Error(exception);
-
-                                throw;
-                            }
-
-                            var group = default(Grouping<TKey, TElement>);
-                            if (!map.TryGetValue(key, out group))
-                            {
-                                group = new Grouping<TKey, TElement>(key, iterateSource, refCount);
-                                map.Add(key, group);
-                                lock (list)
-                                    list.Add(group);
-
-                                Interlocked.Increment(ref count);
-                            }
-                            group.Add(element);
-                        }
-
-                        return res.Value;
-                    }
-                    catch (Exception ex)
-                    {
-                        foreach (var v in map.Values)
-                            v.Error(ex);
-
-                        faulted = ExceptionDispatchInfo.Capture(ex);
-                        throw;
-                    }
-                    finally
-                    {
-                        res = null;
-                    }
-                };
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    var result = await iterateSource(ct).ConfigureAwait(false);
-
-                    current = null;
-                    lock (list)
-                    {
-                        if (index < list.Count)
-                            current = list[index++];
-                    }
-
-                    if (current != null)
-                    {
-                        return true;
-                    }
-                    return result && await f(ct).ConfigureAwait(false);
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<IAsyncGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (elementSelector == null)
-                throw new ArgumentNullException(nameof(elementSelector));
-
-            return source.GroupBy(keySelector, elementSelector, EqualityComparer<TKey>.Default);
-        }
-
-        public static IAsyncEnumerable<IAsyncGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.GroupBy(keySelector, x => x, comparer);
-        }
-
-        public static IAsyncEnumerable<IAsyncGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return source.GroupBy(keySelector, x => x, EqualityComparer<TKey>.Default);
-        }
-
-        public static IAsyncEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IAsyncEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (elementSelector == null)
-                throw new ArgumentNullException(nameof(elementSelector));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.GroupBy(keySelector, elementSelector, comparer).Select(g => resultSelector(g.Key, g));
-        }
-
-        public static IAsyncEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IAsyncEnumerable<TElement>, TResult> resultSelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (elementSelector == null)
-                throw new ArgumentNullException(nameof(elementSelector));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-
-            return source.GroupBy(keySelector, elementSelector, EqualityComparer<TKey>.Default).Select(g => resultSelector(g.Key, g));
-        }
-
-        public static IAsyncEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IAsyncEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.GroupBy(keySelector, x => x, comparer).Select(g => resultSelector(g.Key, g));
-        }
-
-        public static IAsyncEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IAsyncEnumerable<TSource>, TResult> resultSelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-
-            return source.GroupBy(keySelector, x => x, EqualityComparer<TKey>.Default).Select(g => resultSelector(g.Key, g));
-        }
-
-        class Grouping<TKey, TElement> : IAsyncGrouping<TKey, TElement>
-        {
-            private readonly Func<CancellationToken, Task<bool>> iterateSource;
-            private readonly IDisposable sourceDisposable;
-            private readonly List<TElement> elements = new List<TElement>();
-            private bool done = false;
-            private ExceptionDispatchInfo exception = null;
-
-            public Grouping(TKey key, Func<CancellationToken, Task<bool>> iterateSource, IDisposable sourceDisposable)
-            {
-                this.iterateSource = iterateSource;
-                this.sourceDisposable = sourceDisposable;
-                Key = key;
-            }
-
-            public TKey Key
-            {
-                get;
-                private set;
-            }
-
-            public void Add(TElement element)
-            {
-                lock (elements)
-                    elements.Add(element);
-            }
-
-            public void Error(Exception exception)
-            {
-                done = true;
-                this.exception = ExceptionDispatchInfo.Capture(exception);
-            }
-
-            public IAsyncEnumerator<TElement> GetEnumerator()
-            {
-                var index = -1;
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, sourceDisposable);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    var size = 0;
-                    lock (elements)
-                        size = elements.Count;
-
-                    if (index < size)
-                    {
-                        return true;
-                    }
-                    if (done)
-                    {
-                        exception?.Throw();
-                        return false;
-                    }
-                    if (await iterateSource(ct).ConfigureAwait(false))
-                    {
-                        return await f(ct).ConfigureAwait(false);
-                    }
-                    return false;
-                };
-
-                return Create(
-                    ct =>
-                    {
-                        ++index;
-                        return f(cts.Token);
-                    },
-                    () => elements[index],
-                    d.Dispose,
-                    null
-                );
-            }
-        }
-
-        #region Ix
-
-        public static IAsyncEnumerable<TSource> Do<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> onNext)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (onNext == null)
-                throw new ArgumentNullException(nameof(onNext));
-
-            return DoHelper(source, onNext, _ => { }, () => { });
-        }
-
-        public static IAsyncEnumerable<TSource> Do<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (onNext == null)
-                throw new ArgumentNullException(nameof(onNext));
-            if (onCompleted == null)
-                throw new ArgumentNullException(nameof(onCompleted));
-
-            return DoHelper(source, onNext, _ => { }, onCompleted);
-        }
-
-        public static IAsyncEnumerable<TSource> Do<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (onNext == null)
-                throw new ArgumentNullException(nameof(onNext));
-            if (onError == null)
-                throw new ArgumentNullException(nameof(onError));
-
-            return DoHelper(source, onNext, onError, () => { });
-        }
-
-        public static IAsyncEnumerable<TSource> Do<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (onNext == null)
-                throw new ArgumentNullException(nameof(onNext));
-            if (onError == null)
-                throw new ArgumentNullException(nameof(onError));
-            if (onCompleted == null)
-                throw new ArgumentNullException(nameof(onCompleted));
-
-            return DoHelper(source, onNext, onError, onCompleted);
-        }
-
-#if !NO_RXINTERFACES
-        public static IAsyncEnumerable<TSource> Do<TSource>(this IAsyncEnumerable<TSource> source, IObserver<TSource> observer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (observer == null)
-                throw new ArgumentNullException(nameof(observer));
-
-            return DoHelper(source, observer.OnNext, observer.OnError, observer.OnCompleted);
-        }
-#endif
-
-        private static IAsyncEnumerable<TSource> DoHelper<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
-        {
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var current = default(TSource);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    try
-                    {
-                        var result = await e.MoveNext(ct).ConfigureAwait(false);
-                        if (!result)
-                        {
-                            onCompleted();
-                        }
-                        else
-                        {
-                            current = e.Current;
-                            onNext(current);
-                        }
-                        return result;
-                    }
-                    catch (OperationCanceledException)
-                    {
-                        throw;
-                    }
-                    catch (Exception ex)
-                    {
-                        onError(ex);
-                        throw;
-                    }
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static void ForEach<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> action, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (action == null)
-                throw new ArgumentNullException(nameof(action));
-
-            source.ForEachAsync(action, cancellationToken).Wait(cancellationToken);
-        }
-
-        public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> action, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (action == null)
-                throw new ArgumentNullException(nameof(action));
-
-            return source.ForEachAsync((x, i) => action(x), cancellationToken);
-        }
-
-        public static void ForEach<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource, int> action, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (action == null)
-                throw new ArgumentNullException(nameof(action));
-
-            source.ForEachAsync(action, cancellationToken).Wait(cancellationToken);
-        }
-
-        public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource, int> action, CancellationToken cancellationToken)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (action == null)
-                throw new ArgumentNullException(nameof(action));
-
-            return ForEachAsync_(source, action, cancellationToken);
-        }
-
-        private static async Task ForEachAsync_<TSource>(IAsyncEnumerable<TSource> source, Action<TSource, int> action, CancellationToken cancellationToken)
-        {
-            var index = 0;
-            using (var e = source.GetEnumerator())
-            {
-                while (await e.MoveNext(cancellationToken).ConfigureAwait(false))
-                {
-                    action(e.Current, checked(index++));
-                }
-            }
-        }
-
-        public static IAsyncEnumerable<TSource> Repeat<TSource>(this IAsyncEnumerable<TSource> source, int count)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (count < 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-
-            return Create(() =>
-            {
-                var e = default(IAsyncEnumerator<TSource>);
-                var a = new AssignableDisposable();
-                var n = count;
-                var current = default(TSource);
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, a);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (e == null)
-                    {
-                        if (n-- == 0)
-                        {
-                            return false;
-                        }
-
-                        e = source.GetEnumerator();
-
-                        a.Disposable = e;
-                    }
-
-                    if (await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        current = e.Current;
-                        return true;
-                    }
-                    e = null;
-                    return await f(ct).ConfigureAwait(false);
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Repeat<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Create(() =>
-            {
-                var e = default(IAsyncEnumerator<TSource>);
-                var a = new AssignableDisposable();
-                var current = default(TSource);
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, a);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (e == null)
-                    {
-                        e = source.GetEnumerator();
-
-                        a.Disposable = e;
-                    }
-
-                    if (await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        current = e.Current;
-                        return true;
-                    }
-                    e = null;
-                    return await f(ct).ConfigureAwait(false);
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> IgnoreElements<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (!await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        return false;
-                    }
-
-                    return await f(ct).ConfigureAwait(false);
-                };
-
-                return Create<TSource>(
-                    f,
-                    () => { throw new InvalidOperationException(); },
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> StartWith<TSource>(this IAsyncEnumerable<TSource> source, params TSource[] values)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return values.ToAsyncEnumerable().Concat(source);
-        }
-
-        public static IAsyncEnumerable<IList<TSource>> Buffer<TSource>(this IAsyncEnumerable<TSource> source, int count)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (count <= 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-
-            return source.Buffer_(count, count);
-        }
-
-        public static IAsyncEnumerable<IList<TSource>> Buffer<TSource>(this IAsyncEnumerable<TSource> source, int count, int skip)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (count <= 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-            if (skip <= 0)
-                throw new ArgumentOutOfRangeException(nameof(skip));
-
-            return source.Buffer_(count, skip);
-        }
-
-        private static IAsyncEnumerable<IList<TSource>> Buffer_<TSource>(this IAsyncEnumerable<TSource> source, int count, int skip)
-        {
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var buffers = new Queue<IList<TSource>>();
-
-                var i = 0;
-
-                var current = default(IList<TSource>);
-                var stopped = false;
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (!stopped)
-                    {
-                        if (await e.MoveNext(ct).ConfigureAwait(false))
-                        {
-                            var item = e.Current;
-
-                            if (i++ % skip == 0)
-                                buffers.Enqueue(new List<TSource>(count));
-
-                            foreach (var buffer in buffers)
-                                buffer.Add(item);
-
-                            if (buffers.Count > 0 && buffers.Peek().Count == count)
-                            {
-                                current = buffers.Dequeue();
-                                return true;
-                            }
-                            return await f(ct).ConfigureAwait(false);
-                        }
-                        stopped = true;
-                        e.Dispose();
-
-                        return await f(ct).ConfigureAwait(false);
-                    }
-                    if (buffers.Count > 0)
-                    {
-                        current = buffers.Dequeue();
-                        return true;
-                    }
-                    return false;
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return Defer(() =>
-            {
-                var set = new HashSet<TKey>(comparer);
-                return source.Where(item => set.Add(keySelector(item)));
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return source.Distinct(keySelector, EqualityComparer<TKey>.Default);
-        }
-
-        public static IAsyncEnumerable<TSource> DistinctUntilChanged<TSource>(this IAsyncEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.DistinctUntilChanged_(x => x, EqualityComparer<TSource>.Default);
-        }
-
-        public static IAsyncEnumerable<TSource> DistinctUntilChanged<TSource>(this IAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.DistinctUntilChanged_(x => x, comparer);
-        }
-
-        public static IAsyncEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return source.DistinctUntilChanged_(keySelector, EqualityComparer<TKey>.Default);
-        }
-
-        public static IAsyncEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.DistinctUntilChanged_(keySelector, comparer);
-        }
-
-        private static IAsyncEnumerable<TSource> DistinctUntilChanged_<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
-        {
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var currentKey = default(TKey);
-                var hasCurrentKey = false;
-                var current = default(TSource);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        var item = e.Current;
-                        var key = default(TKey);
-                        var comparerEquals = false;
-
-                        key = keySelector(item);
-
-                        if (hasCurrentKey)
-                        {
-                            comparerEquals = comparer.Equals(currentKey, key);
-                        }
-
-                        if (!hasCurrentKey || !comparerEquals)
-                        {
-                            hasCurrentKey = true;
-                            currentKey = key;
-
-                            current = item;
-                            return true;
-                        }
-                        return await f(ct).ConfigureAwait(false);
-                    }
-                    return false;
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Expand<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, IAsyncEnumerable<TSource>> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return Create(() =>
-            {
-                var e = default(IAsyncEnumerator<TSource>);
-
-                var cts = new CancellationTokenDisposable();
-                var a = new AssignableDisposable();
-                var d = Disposable.Create(cts, a);
-
-                var queue = new Queue<IAsyncEnumerable<TSource>>();
-                queue.Enqueue(source);
-
-                var current = default(TSource);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (e == null)
-                    {
-                        if (queue.Count > 0)
-                        {
-                            var src = queue.Dequeue();
-
-                            e = src.GetEnumerator();
-
-                            a.Disposable = e;
-                            return await f(ct).ConfigureAwait(false);
-                        }
-                        return false;
-                    }
-                    if (await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        var item = e.Current;
-                        var next = selector(item);
-
-                        queue.Enqueue(next);
-                        current = item;
-                        return true;
-                    }
-                    e = null;
-                    return await f(ct).ConfigureAwait(false);
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TAccumulate> Scan<TSource, TAccumulate>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (accumulator == null)
-                throw new ArgumentNullException(nameof(accumulator));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var acc = seed;
-                var current = default(TAccumulate);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (!await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        return false;
-                    }
-
-                    var item = e.Current;
-                    acc = accumulator(acc, item);
-
-                    current = acc;
-                    return true;
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> Scan<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (accumulator == null)
-                throw new ArgumentNullException(nameof(accumulator));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var hasSeed = false;
-                var acc = default(TSource);
-                var current = default(TSource);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (!await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        return false;
-                    }
-
-                    var item = e.Current;
-
-                    if (!hasSeed)
-                    {
-                        hasSeed = true;
-                        acc = item;
-                        return await f(ct).ConfigureAwait(false);
-                    }
-
-                    acc = accumulator(acc, item);
-
-                    current = acc;
-                    return true;
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> TakeLast<TSource>(this IAsyncEnumerable<TSource> source, int count)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (count < 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var q = new Queue<TSource>(count);
-                var done = false;
-                var current = default(TSource);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (!done)
-                    {
-                        if (await e.MoveNext(ct).ConfigureAwait(false))
-                        {
-                            if (count > 0)
-                            {
-                                var item = e.Current;
-                                if (q.Count >= count)
-                                    q.Dequeue();
-                                q.Enqueue(item);
-                            }
-                        }
-                        else
-                        {
-                            done = true;
-                            e.Dispose();
-                        }
-
-                        return await f(ct).ConfigureAwait(false);
-                    }
-                    if (q.Count > 0)
-                    {
-                        current = q.Dequeue();
-                        return true;
-                    }
-                    return false;
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        public static IAsyncEnumerable<TSource> SkipLast<TSource>(this IAsyncEnumerable<TSource> source, int count)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (count < 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-
-            return Create(() =>
-            {
-                var e = source.GetEnumerator();
-
-                var cts = new CancellationTokenDisposable();
-                var d = Disposable.Create(cts, e);
-
-                var q = new Queue<TSource>();
-                var current = default(TSource);
-
-                var f = default(Func<CancellationToken, Task<bool>>);
-                f = async ct =>
-                {
-                    if (await e.MoveNext(ct).ConfigureAwait(false))
-                    {
-                        var item = e.Current;
-
-                        q.Enqueue(item);
-                        if (q.Count > count)
-                        {
-                            current = q.Dequeue();
-                            return true;
-                        }
-                        return await f(ct).ConfigureAwait(false);
-                    }
-                    return false;
-                };
-
-                return Create(
-                    f,
-                    () => current,
-                    d.Dispose,
-                    e
-                );
-            });
-        }
-
-        #endregion
-    }
-}

+ 81 - 0
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.cs

@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> AsAsyncEnumerable<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Select(x => x);
+        }
+
+        public static IAsyncEnumerable<TValue> Empty<TValue>()
+        {
+            return Create(() => Create<TValue>(
+                              ct => TaskExt.False,
+                              () => { throw new InvalidOperationException(); },
+                              () => { })
+            );
+        }
+
+        public static Task<bool> IsEmpty<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return source.IsEmpty(CancellationToken.None);
+        }
+
+        public static Task<bool> IsEmpty<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return IsEmpty_(source, cancellationToken);
+        }
+
+        public static IAsyncEnumerable<TValue> Never<TValue>()
+        {
+            return Create(() => Create<TValue>(
+                              (ct, tcs) => tcs.Task,
+                              () => { throw new InvalidOperationException(); },
+                              () => { })
+            );
+        }
+
+
+        public static IAsyncEnumerable<TValue> Return<TValue>(TValue value)
+        {
+            return new[] {value}.ToAsyncEnumerable();
+        }
+
+        public static IAsyncEnumerable<TValue> Throw<TValue>(Exception exception)
+        {
+            if (exception == null)
+                throw new ArgumentNullException(nameof(exception));
+
+            return Create(() => Create<TValue>(
+                              ct => TaskExt.Throw<bool>(exception),
+                              () => { throw new InvalidOperationException(); },
+                              () => { })
+            );
+        }
+
+        private static async Task<bool> IsEmpty_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            return !await source.Any(cancellationToken)
+                                .ConfigureAwait(false);
+        }
+    }
+}

+ 675 - 0
Ix.NET/Source/System.Interactive.Async/Average.cs

@@ -0,0 +1,675 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<double> Average(this IAsyncEnumerable<int> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            return Average(source, CancellationToken.None);
+        }
+
+        public static Task<double?> Average(this IAsyncEnumerable<int?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            return Average(source, CancellationToken.None);
+        }
+
+        public static Task<double> Average(this IAsyncEnumerable<long> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Average(source, CancellationToken.None);
+        }
+
+        public static Task<double?> Average(this IAsyncEnumerable<long?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Average(source, CancellationToken.None);
+        }
+
+        public static Task<double> Average(this IAsyncEnumerable<double> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Average(source, CancellationToken.None);
+        }
+
+        public static Task<double?> Average(this IAsyncEnumerable<double?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Average(source, CancellationToken.None);
+        }
+
+        public static Task<float> Average(this IAsyncEnumerable<float> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Average(source, CancellationToken.None);
+        }
+
+        public static Task<float?> Average(this IAsyncEnumerable<float?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Average(source, CancellationToken.None);
+        }
+
+        public static Task<decimal> Average(this IAsyncEnumerable<decimal> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Average(source, CancellationToken.None);
+        }
+
+        public static Task<decimal?> Average(this IAsyncEnumerable<decimal?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Average(source, CancellationToken.None);
+        }
+
+        public static Task<double?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Average(source, selector, CancellationToken.None);
+        }
+
+        public static Task<double> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Average(source, selector, CancellationToken.None);
+        }
+
+        public static Task<double> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Average(source, selector, CancellationToken.None);
+        }
+
+        public static Task<double?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Average(source, selector, CancellationToken.None);
+        }
+
+        public static Task<double> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Average(source, selector, CancellationToken.None);
+        }
+
+        public static Task<double?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Average(source, selector, CancellationToken.None);
+        }
+
+        public static Task<float> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Average(source, selector, CancellationToken.None);
+        }
+
+        public static Task<float?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Average(source, selector, CancellationToken.None);
+        }
+
+        public static Task<decimal> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Average(source, selector, CancellationToken.None);
+        }
+
+        public static Task<decimal?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Average(source, selector, CancellationToken.None);
+        }
+
+
+        public static Task<double> Average(this IAsyncEnumerable<int> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Average_(source, cancellationToken);
+        }
+
+        public static Task<double?> Average(this IAsyncEnumerable<int?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Average_(source, cancellationToken);
+        }
+
+        public static Task<double> Average(this IAsyncEnumerable<long> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Average_(source, cancellationToken);
+        }
+
+        public static Task<double?> Average(this IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Average_(source, cancellationToken);
+        }
+
+        public static Task<double> Average(this IAsyncEnumerable<double> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Average_(source, cancellationToken);
+        }
+
+        public static Task<double?> Average(this IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Average_(source, cancellationToken);
+        }
+
+        public static Task<float> Average(this IAsyncEnumerable<float> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Average_(source, cancellationToken);
+        }
+
+        public static Task<float?> Average(this IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Average_(source, cancellationToken);
+        }
+
+        public static Task<decimal> Average(this IAsyncEnumerable<decimal> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Average_(source, cancellationToken);
+        }
+
+        public static Task<decimal?> Average(this IAsyncEnumerable<decimal?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Average_(source, cancellationToken);
+        }
+
+        public static Task<double?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Average(cancellationToken);
+        }
+
+        public static Task<double> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Average(cancellationToken);
+        }
+
+        public static Task<double> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Average(cancellationToken);
+        }
+
+        public static Task<double?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Average(cancellationToken);
+        }
+
+        public static Task<double> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Average(cancellationToken);
+        }
+
+        public static Task<double?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Average(cancellationToken);
+        }
+
+        public static Task<float> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Average(cancellationToken);
+        }
+
+        public static Task<float?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Average(cancellationToken);
+        }
+
+        public static Task<decimal> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Average(cancellationToken);
+        }
+
+        public static Task<decimal?> Average<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Average(cancellationToken);
+        }
+
+        private static async Task<double> Average_(this IAsyncEnumerable<int> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                if (!await e.MoveNext(cancellationToken)
+                            .ConfigureAwait(false))
+                {
+                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
+                }
+
+                long sum = e.Current;
+                long count = 1;
+                checked
+                {
+                    while (await e.MoveNext(cancellationToken)
+                                  .ConfigureAwait(false))
+                    {
+                        sum += e.Current;
+                        ++count;
+                    }
+                }
+
+                return (double)sum/count;
+            }
+        }
+
+        private static async Task<double?> Average_(IAsyncEnumerable<int?> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    var v = e.Current;
+                    if (v.HasValue)
+                    {
+                        long sum = v.GetValueOrDefault();
+                        long count = 1;
+                        checked
+                        {
+                            while (await e.MoveNext(cancellationToken)
+                                          .ConfigureAwait(false))
+                            {
+                                v = e.Current;
+                                if (v.HasValue)
+                                {
+                                    sum += v.GetValueOrDefault();
+                                    ++count;
+                                }
+                            }
+                        }
+
+                        return (double)sum/count;
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        private static async Task<double> Average_(IAsyncEnumerable<long> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                if (!await e.MoveNext(cancellationToken)
+                            .ConfigureAwait(false))
+                {
+                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
+                }
+
+                var sum = e.Current;
+                long count = 1;
+                checked
+                {
+                    while (await e.MoveNext(cancellationToken)
+                                  .ConfigureAwait(false))
+                    {
+                        sum += e.Current;
+                        ++count;
+                    }
+                }
+
+                return (double)sum/count;
+            }
+        }
+
+        private static async Task<double?> Average_(IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    var v = e.Current;
+                    if (v.HasValue)
+                    {
+                        var sum = v.GetValueOrDefault();
+                        long count = 1;
+                        checked
+                        {
+                            while (await e.MoveNext(cancellationToken)
+                                          .ConfigureAwait(false))
+                            {
+                                v = e.Current;
+                                if (v.HasValue)
+                                {
+                                    sum += v.GetValueOrDefault();
+                                    ++count;
+                                }
+                            }
+                        }
+
+                        return (double)sum/count;
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        private static async Task<double> Average_(IAsyncEnumerable<double> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                if (!await e.MoveNext(cancellationToken)
+                            .ConfigureAwait(false))
+                {
+                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
+                }
+
+                var sum = e.Current;
+                long count = 1;
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    // There is an opportunity to short-circuit here, in that if e.Current is
+                    // ever NaN then the result will always be NaN. Assuming that this case is
+                    // rare enough that not checking is the better approach generally.
+                    sum += e.Current;
+                    ++count;
+                }
+
+                return sum/count;
+            }
+        }
+
+        private static async Task<double?> Average_(IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    var v = e.Current;
+                    if (v.HasValue)
+                    {
+                        var sum = v.GetValueOrDefault();
+                        long count = 1;
+                        checked
+                        {
+                            while (await e.MoveNext(cancellationToken)
+                                          .ConfigureAwait(false))
+                            {
+                                v = e.Current;
+                                if (v.HasValue)
+                                {
+                                    sum += v.GetValueOrDefault();
+                                    ++count;
+                                }
+                            }
+                        }
+
+                        return sum/count;
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        private static async Task<float> Average_(IAsyncEnumerable<float> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                if (!await e.MoveNext(cancellationToken)
+                            .ConfigureAwait(false))
+                {
+                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
+                }
+
+                double sum = e.Current;
+                long count = 1;
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    sum += e.Current;
+                    ++count;
+                }
+
+                return (float)(sum/count);
+            }
+        }
+
+        private static async Task<float?> Average_(IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    var v = e.Current;
+                    if (v.HasValue)
+                    {
+                        double sum = v.GetValueOrDefault();
+                        long count = 1;
+                        checked
+                        {
+                            while (await e.MoveNext(cancellationToken)
+                                          .ConfigureAwait(false))
+                            {
+                                v = e.Current;
+                                if (v.HasValue)
+                                {
+                                    sum += v.GetValueOrDefault();
+                                    ++count;
+                                }
+                            }
+                        }
+
+                        return (float)(sum/count);
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        private static async Task<decimal> Average_(IAsyncEnumerable<decimal> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                if (!await e.MoveNext(cancellationToken)
+                            .ConfigureAwait(false))
+                {
+                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
+                }
+
+                var sum = e.Current;
+                long count = 1;
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    sum += e.Current;
+                    ++count;
+                }
+
+                return sum/count;
+            }
+        }
+
+        private static async Task<decimal?> Average_(IAsyncEnumerable<decimal?> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    var v = e.Current;
+                    if (v.HasValue)
+                    {
+                        var sum = v.GetValueOrDefault();
+                        long count = 1;
+                        while (await e.MoveNext(cancellationToken)
+                                      .ConfigureAwait(false))
+                        {
+                            v = e.Current;
+                            if (v.HasValue)
+                            {
+                                sum += v.GetValueOrDefault();
+                                ++count;
+                            }
+                        }
+
+                        return sum/count;
+                    }
+                }
+            }
+
+            return null;
+        }
+    }
+}

+ 101 - 0
Ix.NET/Source/System.Interactive.Async/Buffer.cs

@@ -0,0 +1,101 @@
+// // Licensed to the .NET Foundation under one or more agreements.
+// // The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// // See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<IList<TSource>> Buffer<TSource>(this IAsyncEnumerable<TSource> source, int count)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count <= 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            return source.Buffer_(count, count);
+        }
+
+        public static IAsyncEnumerable<IList<TSource>> Buffer<TSource>(this IAsyncEnumerable<TSource> source, int count, int skip)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count <= 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+            if (skip <= 0)
+                throw new ArgumentOutOfRangeException(nameof(skip));
+
+            return source.Buffer_(count, skip);
+        }
+
+        private static IAsyncEnumerable<IList<TSource>> Buffer_<TSource>(this IAsyncEnumerable<TSource> source, int count, int skip)
+        {
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var buffers = new Queue<IList<TSource>>();
+
+                              var i = 0;
+
+                              var current = default(IList<TSource>);
+                              var stopped = false;
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (!stopped)
+                                      {
+                                          if (await e.MoveNext(ct)
+                                                     .ConfigureAwait(false))
+                                          {
+                                              var item = e.Current;
+
+                                              if (i++%skip == 0)
+                                                  buffers.Enqueue(new List<TSource>(count));
+
+                                              foreach (var buffer in buffers)
+                                                  buffer.Add(item);
+
+                                              if (buffers.Count > 0 && buffers.Peek()
+                                                                              .Count == count)
+                                              {
+                                                  current = buffers.Dequeue();
+                                                  return true;
+                                              }
+                                              return await f(ct)
+                                                         .ConfigureAwait(false);
+                                          }
+                                          stopped = true;
+                                          e.Dispose();
+
+                                          return await f(ct)
+                                                     .ConfigureAwait(false);
+                                      }
+                                      if (buffers.Count > 0)
+                                      {
+                                          current = buffers.Dequeue();
+                                          return true;
+                                      }
+                                      return false;
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 31 - 0
Ix.NET/Source/System.Interactive.Async/Cast.cs

@@ -0,0 +1,31 @@
+// // Licensed to the .NET Foundation under one or more agreements.
+// // The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// // See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TResult> Cast<TResult>(this IAsyncEnumerable<object> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Select(x => (TResult)x);
+        }
+
+        public static IAsyncEnumerable<TType> OfType<TType>(this IAsyncEnumerable<object> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Where(x => x is TType)
+                         .Cast<TType>();
+        }
+    }
+}

+ 153 - 0
Ix.NET/Source/System.Interactive.Async/Catch.cs

@@ -0,0 +1,153 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.ExceptionServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Catch<TSource, TException>(this IAsyncEnumerable<TSource> source, Func<TException, IAsyncEnumerable<TSource>> handler)
+            where TException : Exception
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (handler == null)
+                throw new ArgumentNullException(nameof(handler));
+
+            return Create(() =>
+            {
+                var e = source.GetEnumerator();
+
+                var cts = new CancellationTokenDisposable();
+                var a = new AssignableDisposable
+                {
+                    Disposable = e
+                };
+                var d = Disposable.Create(cts, a);
+                var done = false;
+
+                var f = default(Func<CancellationToken, Task<bool>>);
+                f = async ct =>
+                {
+                    if (!done)
+                    {
+                        try
+                        {
+                            return await e.MoveNext(ct)
+                                          .ConfigureAwait(false);
+                        }
+                        catch (TException ex)
+                        {
+                            var err = handler(ex)
+                                .GetEnumerator();
+                            e = err;
+                            a.Disposable = e;
+                            done = true;
+                            return await f(ct)
+                                       .ConfigureAwait(false);
+                        }
+                    }
+                    return await e.MoveNext(ct)
+                                  .ConfigureAwait(false);
+                };
+
+                return Create(
+                    f,
+                    () => e.Current,
+                    d.Dispose,
+                    a
+                );
+            });
+        }
+
+        public static IAsyncEnumerable<TSource> Catch<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return sources.Catch_();
+        }
+
+        public static IAsyncEnumerable<TSource> Catch<TSource>(params IAsyncEnumerable<TSource>[] sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return sources.Catch_();
+        }
+
+        public static IAsyncEnumerable<TSource> Catch<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            return new[] { first, second }.Catch_();
+        }
+
+        private static IAsyncEnumerable<TSource> Catch_<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
+        {
+            return Create(() =>
+            {
+                var se = sources.GetEnumerator();
+                var e = default(IAsyncEnumerator<TSource>);
+
+                var cts = new CancellationTokenDisposable();
+                var a = new AssignableDisposable();
+                var d = Disposable.Create(cts, se, a);
+
+                var error = default(ExceptionDispatchInfo);
+
+                var f = default(Func<CancellationToken, Task<bool>>);
+                f = async ct =>
+                {
+                    if (e == null)
+                    {
+                        if (se.MoveNext())
+                        {
+                            e = se.Current.GetEnumerator();
+                        }
+                        else
+                        {
+                            error?.Throw();
+                            return false;
+                        }
+
+                        error = null;
+
+                        a.Disposable = e;
+                    }
+
+                    try
+                    {
+                        return await e.MoveNext(ct)
+                                      .ConfigureAwait(false);
+                    }
+                    catch (Exception exception)
+                    {
+                        e.Dispose();
+                        e = null;
+                        error = ExceptionDispatchInfo.Capture(exception);
+                        return await f(ct)
+                                   .ConfigureAwait(false);
+                    }
+                };
+
+                return Create(
+                    f,
+                    () => e.Current,
+                    d.Dispose,
+                    a
+                );
+            });
+        }
+    }
+}

+ 130 - 0
Ix.NET/Source/System.Interactive.Async/Concatenate.cs

@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Concat<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            return Create(() =>
+                          {
+                              var switched = false;
+                              var e = first.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var a = new AssignableDisposable
+                              {
+                                  Disposable = e
+                              };
+                              var d = Disposable.Create(cts, a);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (await e.MoveNext(ct)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          return true;
+                                      }
+                                      if (switched)
+                                      {
+                                          return false;
+                                      }
+                                      switched = true;
+
+                                      e = second.GetEnumerator();
+                                      a.Disposable = e;
+
+                                      return await f(ct)
+                                                 .ConfigureAwait(false);
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => e.Current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TSource> Concat<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return sources.Concat_();
+        }
+
+        public static IAsyncEnumerable<TSource> Concat<TSource>(params IAsyncEnumerable<TSource>[] sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return sources.Concat_();
+        }
+
+        private static IAsyncEnumerable<TSource> Concat_<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
+        {
+            return Create(() =>
+                          {
+                              var se = sources.GetEnumerator();
+                              var e = default(IAsyncEnumerator<TSource>);
+
+                              var cts = new CancellationTokenDisposable();
+                              var a = new AssignableDisposable();
+                              var d = Disposable.Create(cts, se, a);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (e == null)
+                                      {
+                                          var b = false;
+                                          b = se.MoveNext();
+                                          if (b)
+                                              e = se.Current.GetEnumerator();
+
+                                          if (!b)
+                                          {
+                                              return false;
+                                          }
+
+                                          a.Disposable = e;
+                                      }
+
+                                      if (await e.MoveNext(ct)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          return true;
+                                      }
+                                      e.Dispose();
+                                      e = null;
+
+                                      return await f(ct)
+                                                 .ConfigureAwait(false);
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => e.Current,
+                                  d.Dispose,
+                                  a
+                              );
+                          });
+        }
+    }
+}

+ 51 - 0
Ix.NET/Source/System.Interactive.Async/Contains.cs

@@ -0,0 +1,51 @@
+// // Licensed to the .NET Foundation under one or more agreements.
+// // The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// // See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<bool> Contains<TSource>(this IAsyncEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (comparer == null)
+                throw new ArgumentNullException("comparer");
+
+            return Contains(source, value, comparer, CancellationToken.None);
+        }
+
+        public static Task<bool> Contains<TSource>(this IAsyncEnumerable<TSource> source, TSource value)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Contains(source, value, CancellationToken.None);
+        }
+
+        public static Task<bool> Contains<TSource>(this IAsyncEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.Any(x => comparer.Equals(x, value), cancellationToken);
+        }
+
+        public static Task<bool> Contains<TSource>(this IAsyncEnumerable<TSource> source, TSource value, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Contains(value, EqualityComparer<TSource>.Default, cancellationToken);
+        }
+    }
+}

+ 89 - 0
Ix.NET/Source/System.Interactive.Async/Count.cs

@@ -0,0 +1,89 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<int> Count<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(0, (c, _) => checked(c + 1), cancellationToken);
+        }
+
+        public static Task<int> Count<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return source.Where(predicate)
+                         .Aggregate(0, (c, _) => checked(c + 1), cancellationToken);
+        }
+
+        public static Task<int> Count<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Count(source, CancellationToken.None);
+        }
+
+        public static Task<int> Count<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (predicate == null)
+                throw new ArgumentNullException("predicate");
+
+            return Count(source, predicate, CancellationToken.None);
+        }
+
+        public static Task<long> LongCount<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(0L, (c, _) => checked(c + 1), cancellationToken);
+        }
+
+        public static Task<long> LongCount<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return source.Where(predicate)
+                         .Aggregate(0L, (c, _) => checked(c + 1), cancellationToken);
+        }
+
+        public static Task<long> LongCount<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return LongCount(source, CancellationToken.None);
+        }
+
+        public static Task<long> LongCount<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (predicate == null)
+                throw new ArgumentNullException("predicate");
+
+            return LongCount(source, predicate, CancellationToken.None);
+        }
+    }
+}

+ 136 - 0
Ix.NET/Source/System.Interactive.Async/Create.cs

@@ -0,0 +1,136 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<T> Create<T>(Func<IAsyncEnumerator<T>> getEnumerator)
+        {
+            return new AnonymousAsyncEnumerable<T>(getEnumerator);
+        }
+
+        private class AnonymousAsyncEnumerable<T> : IAsyncEnumerable<T>
+        {
+            private Func<IAsyncEnumerator<T>> getEnumerator;
+
+            public AnonymousAsyncEnumerable(Func<IAsyncEnumerator<T>> getEnumerator)
+            {
+                this.getEnumerator = getEnumerator;
+            }
+
+            public IAsyncEnumerator<T> GetEnumerator()
+            {
+                return getEnumerator();
+            }
+        }
+
+        private static IAsyncEnumerator<T> Create<T>(Func<CancellationToken, Task<bool>> moveNext, Func<T> current,
+            Action dispose, IDisposable enumerator)
+        {
+            return Create(async ct =>
+            {
+                using (ct.Register(dispose))
+                {
+                    try
+                    {
+                        var result = await moveNext(ct).ConfigureAwait(false);
+                        if (!result)
+                        {
+                            enumerator?.Dispose();
+                        }
+                        return result;
+                    }
+                    catch
+                    {
+                        enumerator?.Dispose();
+                        throw;
+                    }
+                }
+            }, current, dispose);
+        }
+
+        public static IAsyncEnumerator<T> Create<T>(Func<CancellationToken, Task<bool>> moveNext, Func<T> current, Action dispose)
+        {
+            return new AnonymousAsyncEnumerator<T>(moveNext, current, dispose);
+        }
+
+        private static IAsyncEnumerator<T> Create<T>(Func<CancellationToken, TaskCompletionSource<bool>, Task<bool>> moveNext, Func<T> current, Action dispose)
+        {
+            var self = default(IAsyncEnumerator<T>);
+            self = new AnonymousAsyncEnumerator<T>(
+                async ct =>
+                {
+                    var tcs = new TaskCompletionSource<bool>();
+
+                    var stop = new Action(() =>
+                    {
+                        self.Dispose();
+                        tcs.TrySetCanceled();
+                    });
+
+                    using (ct.Register(stop))
+                    {
+                        return await moveNext(ct, tcs).ConfigureAwait(false);
+                    }
+                },
+                current,
+                dispose
+            );
+            return self;
+        }
+
+        private class AnonymousAsyncEnumerator<T> : IAsyncEnumerator<T>
+        {
+            private readonly Func<CancellationToken, Task<bool>> _moveNext;
+            private readonly Func<T> _current;
+            private readonly Action _dispose;
+            private bool _disposed;
+
+            public AnonymousAsyncEnumerator(Func<CancellationToken, Task<bool>> moveNext, Func<T> current, Action dispose)
+            {
+                _moveNext = moveNext;
+                _current = current;
+                _dispose = dispose;
+            }
+
+            public Task<bool> MoveNext(CancellationToken cancellationToken)
+            {
+                if (_disposed)
+                    return TaskExt.False;
+
+                return _moveNext(cancellationToken);
+            }
+
+            public T Current
+            {
+                get
+                {
+                    return _current();
+                }
+            }
+
+            public void Dispose()
+            {
+                if (!_disposed)
+                {
+                    _disposed = true;
+                    _dispose();
+                }
+            }
+        }
+
+
+
+
+      
+
+
+    }
+}

+ 68 - 0
Ix.NET/Source/System.Interactive.Async/DefaultIfEmpty.cs

@@ -0,0 +1,68 @@
+// // Licensed to the .NET Foundation under one or more agreements.
+// // The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// // See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> DefaultIfEmpty<TSource>(this IAsyncEnumerable<TSource> source, TSource defaultValue)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create(() =>
+                          {
+                              var done = false;
+                              var hasElements = false;
+                              var e = source.GetEnumerator();
+                              var current = default(TSource);
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (done)
+                                          return false;
+                                      if (await e.MoveNext(ct)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          hasElements = true;
+                                          current = e.Current;
+                                          return true;
+                                      }
+                                      done = true;
+                                      if (!hasElements)
+                                      {
+                                          current = defaultValue;
+                                          return true;
+                                      }
+                                      return false;
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TSource> DefaultIfEmpty<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.DefaultIfEmpty(default(TSource));
+        }
+    }
+}

+ 23 - 0
Ix.NET/Source/System.Interactive.Async/Defer.cs

@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Defer<TSource>(Func<IAsyncEnumerable<TSource>> factory)
+        {
+            if (factory == null)
+                throw new ArgumentNullException(nameof(factory));
+
+            return Create(() => factory()
+                              .GetEnumerator());
+        }
+    }
+}

+ 156 - 0
Ix.NET/Source/System.Interactive.Async/Distinct.cs

@@ -0,0 +1,156 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Defer(() =>
+                         {
+                             var set = new HashSet<TKey>(comparer);
+                             return source.Where(item => set.Add(keySelector(item)));
+                         });
+        }
+
+        public static IAsyncEnumerable<TSource> Distinct<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Distinct(keySelector, EqualityComparer<TKey>.Default);
+        }
+
+        public static IAsyncEnumerable<TSource> Distinct<TSource>(this IAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Defer(() =>
+                         {
+                             var set = new HashSet<TSource>(comparer);
+                             return source.Where(set.Add);
+                         });
+        }
+
+        public static IAsyncEnumerable<TSource> Distinct<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Distinct(EqualityComparer<TSource>.Default);
+        }
+
+        public static IAsyncEnumerable<TSource> DistinctUntilChanged<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.DistinctUntilChanged_(x => x, EqualityComparer<TSource>.Default);
+        }
+
+        public static IAsyncEnumerable<TSource> DistinctUntilChanged<TSource>(this IAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.DistinctUntilChanged_(x => x, comparer);
+        }
+
+        public static IAsyncEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.DistinctUntilChanged_(keySelector, EqualityComparer<TKey>.Default);
+        }
+
+        public static IAsyncEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.DistinctUntilChanged_(keySelector, comparer);
+        }
+
+        private static IAsyncEnumerable<TSource> DistinctUntilChanged_<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var currentKey = default(TKey);
+                              var hasCurrentKey = false;
+                              var current = default(TSource);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (await e.MoveNext(ct)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          var item = e.Current;
+                                          var key = default(TKey);
+                                          var comparerEquals = false;
+
+                                          key = keySelector(item);
+
+                                          if (hasCurrentKey)
+                                          {
+                                              comparerEquals = comparer.Equals(currentKey, key);
+                                          }
+
+                                          if (!hasCurrentKey || !comparerEquals)
+                                          {
+                                              hasCurrentKey = true;
+                                              currentKey = key;
+
+                                              current = item;
+                                              return true;
+                                          }
+                                          return await f(ct)
+                                                     .ConfigureAwait(false);
+                                      }
+                                      return false;
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 122 - 0
Ix.NET/Source/System.Interactive.Async/Do.cs

@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Do<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> onNext)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            return DoHelper(source, onNext, _ => { }, () => { });
+        }
+
+        public static IAsyncEnumerable<TSource> Do<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return DoHelper(source, onNext, _ => { }, onCompleted);
+        }
+
+        public static IAsyncEnumerable<TSource> Do<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+
+            return DoHelper(source, onNext, onError, () => { });
+        }
+
+        public static IAsyncEnumerable<TSource> Do<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return DoHelper(source, onNext, onError, onCompleted);
+        }
+
+        public static IAsyncEnumerable<TSource> Do<TSource>(this IAsyncEnumerable<TSource> source, IObserver<TSource> observer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return DoHelper(source, observer.OnNext, observer.OnError, observer.OnCompleted);
+        }
+
+        private static IAsyncEnumerable<TSource> DoHelper<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
+        {
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var current = default(TSource);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      try
+                                      {
+                                          var result = await e.MoveNext(ct)
+                                                              .ConfigureAwait(false);
+                                          if (!result)
+                                          {
+                                              onCompleted();
+                                          }
+                                          else
+                                          {
+                                              current = e.Current;
+                                              onNext(current);
+                                          }
+                                          return result;
+                                      }
+                                      catch (OperationCanceledException)
+                                      {
+                                          throw;
+                                      }
+                                      catch (Exception ex)
+                                      {
+                                          onError(ex);
+                                          throw;
+                                      }
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 96 - 0
Ix.NET/Source/System.Interactive.Async/ElementAt.cs

@@ -0,0 +1,96 @@
+// // Licensed to the .NET Foundation under one or more agreements.
+// // The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// // See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<TSource> ElementAt<TSource>(this IAsyncEnumerable<TSource> source, int index, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (index < 0)
+                throw new ArgumentOutOfRangeException(nameof(index));
+
+            return ElementAt_(source, index, cancellationToken);
+        }
+
+
+        public static Task<TSource> ElementAt<TSource>(this IAsyncEnumerable<TSource> source, int index)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return ElementAt(source, index, CancellationToken.None);
+        }
+
+        public static Task<TSource> ElementAtOrDefault<TSource>(this IAsyncEnumerable<TSource> source, int index, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (index < 0)
+                throw new ArgumentOutOfRangeException(nameof(index));
+
+            return ElementAtOrDefault_(source, index, cancellationToken);
+        }
+
+        public static Task<TSource> ElementAtOrDefault<TSource>(this IAsyncEnumerable<TSource> source, int index)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return ElementAtOrDefault(source, index, CancellationToken.None);
+        }
+
+        private static async Task<TSource> ElementAt_<TSource>(IAsyncEnumerable<TSource> source, int index, CancellationToken cancellationToken)
+        {
+            if (index >= 0)
+            {
+                using (var e = source.GetEnumerator())
+                {
+                    while (await e.MoveNext(cancellationToken)
+                                  .ConfigureAwait(false))
+                    {
+                        if (index == 0)
+                        {
+                            return e.Current;
+                        }
+
+                        index--;
+                    }
+                }
+            }
+
+            throw new ArgumentOutOfRangeException(nameof(index));
+        }
+
+        private static async Task<TSource> ElementAtOrDefault_<TSource>(IAsyncEnumerable<TSource> source, int index, CancellationToken cancellationToken)
+        {
+            if (index >= 0)
+            {
+                using (var e = source.GetEnumerator())
+                {
+                    while (await e.MoveNext(cancellationToken)
+                                  .ConfigureAwait(false))
+                    {
+                        if (index == 0)
+                        {
+                            return e.Current;
+                        }
+
+                        index--;
+                    }
+                }
+            }
+
+            return default(TSource);
+        }
+    }
+}

+ 69 - 0
Ix.NET/Source/System.Interactive.Async/Except.cs

@@ -0,0 +1,69 @@
+// // Licensed to the .NET Foundation under one or more agreements.
+// // The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// // See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Except<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            return first.Except(second, EqualityComparer<TSource>.Default);
+        }
+
+        public static IAsyncEnumerable<TSource> Except<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Create(() =>
+                          {
+                              var e = first.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var mapTask = default(Task<Dictionary<TSource, TSource>>);
+                              var getMapTask = new Func<CancellationToken, Task<Dictionary<TSource, TSource>>>(
+                                  ct => mapTask ?? (mapTask = second.ToDictionary(x => x, comparer, ct)));
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (await e.MoveNext(ct)
+                                                 .Zip(getMapTask(ct), (b, _) => b)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          if (!mapTask.Result.ContainsKey(e.Current))
+                                              return true;
+                                          return await f(ct)
+                                                     .ConfigureAwait(false);
+                                      }
+                                      return false;
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => e.Current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 76 - 0
Ix.NET/Source/System.Interactive.Async/Expand.cs

@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Expand<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, IAsyncEnumerable<TSource>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create(() =>
+                          {
+                              var e = default(IAsyncEnumerator<TSource>);
+
+                              var cts = new CancellationTokenDisposable();
+                              var a = new AssignableDisposable();
+                              var d = Disposable.Create(cts, a);
+
+                              var queue = new Queue<IAsyncEnumerable<TSource>>();
+                              queue.Enqueue(source);
+
+                              var current = default(TSource);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (e == null)
+                                      {
+                                          if (queue.Count > 0)
+                                          {
+                                              var src = queue.Dequeue();
+
+                                              e = src.GetEnumerator();
+
+                                              a.Disposable = e;
+                                              return await f(ct)
+                                                         .ConfigureAwait(false);
+                                          }
+                                          return false;
+                                      }
+                                      if (await e.MoveNext(ct)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          var item = e.Current;
+                                          var next = selector(item);
+
+                                          queue.Enqueue(next);
+                                          current = item;
+                                          return true;
+                                      }
+                                      e = null;
+                                      return await f(ct)
+                                                 .ConfigureAwait(false);
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 38 - 0
Ix.NET/Source/System.Interactive.Async/Finally.cs

@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Finally<TSource>(this IAsyncEnumerable<TSource> source, Action finallyAction)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (finallyAction == null)
+                throw new ArgumentNullException(nameof(finallyAction));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var r = new Disposable(finallyAction);
+                              var d = Disposable.Create(cts, e, r);
+
+                              return Create(
+                                  ct => e.MoveNext(ct),
+                                  () => e.Current,
+                                  d.Dispose,
+                                  r
+                              );
+                          });
+        }
+    }
+}

+ 115 - 0
Ix.NET/Source/System.Interactive.Async/First.cs

@@ -0,0 +1,115 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<TSource> First<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return First(source, CancellationToken.None);
+        }
+
+        public static Task<TSource> First<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (predicate == null)
+                throw new ArgumentNullException("predicate");
+
+            return First(source, predicate, CancellationToken.None);
+        }
+
+        public static Task<TSource> First<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return First_(source, cancellationToken);
+        }
+
+        public static Task<TSource> First<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return source.Where(predicate)
+                         .First(cancellationToken);
+        }
+
+        public static Task<TSource> FirstOrDefault<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return FirstOrDefault(source, CancellationToken.None);
+        }
+
+        public static Task<TSource> FirstOrDefault<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (predicate == null)
+                throw new ArgumentNullException("predicate");
+
+            return FirstOrDefault(source, predicate, CancellationToken.None);
+        }
+
+        public static Task<TSource> FirstOrDefault<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return FirstOrDefault_(source, cancellationToken);
+        }
+
+        public static Task<TSource> FirstOrDefault<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return source.Where(predicate)
+                         .FirstOrDefault(cancellationToken);
+        }
+
+        private static async Task<TSource> First_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                if (await e.MoveNext(cancellationToken)
+                           .ConfigureAwait(false))
+                {
+                    return e.Current;
+                }
+            }
+            throw new InvalidOperationException(Strings.NO_ELEMENTS);
+        }
+
+        private static async Task<TSource> FirstOrDefault_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                if (await e.MoveNext(cancellationToken)
+                           .ConfigureAwait(false))
+                {
+                    return e.Current;
+                }
+            }
+            return default(TSource);
+        }
+    }
+}

+ 113 - 0
Ix.NET/Source/System.Interactive.Async/ForEach.cs

@@ -0,0 +1,113 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static void ForEach<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> action)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (action == null)
+                throw new ArgumentNullException("action");
+
+            source.ForEachAsync(action)
+                  .Wait();
+        }
+
+        public static void ForEach<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource, int> action)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (action == null)
+                throw new ArgumentNullException("action");
+
+            source.ForEachAsync(action)
+                  .Wait();
+        }
+
+
+        public static void ForEach<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> action, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (action == null)
+                throw new ArgumentNullException(nameof(action));
+
+            source.ForEachAsync(action, cancellationToken)
+                  .Wait(cancellationToken);
+        }
+
+        public static void ForEach<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource, int> action, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (action == null)
+                throw new ArgumentNullException(nameof(action));
+
+            source.ForEachAsync(action, cancellationToken)
+                  .Wait(cancellationToken);
+        }
+
+        public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> action)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (action == null)
+                throw new ArgumentNullException("action");
+
+            return ForEachAsync(source, action, CancellationToken.None);
+        }
+
+        public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource, int> action)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (action == null)
+                throw new ArgumentNullException("action");
+
+            return ForEachAsync(source, action, CancellationToken.None);
+        }
+
+        public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource> action, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (action == null)
+                throw new ArgumentNullException(nameof(action));
+
+            return source.ForEachAsync((x, i) => action(x), cancellationToken);
+        }
+
+        public static Task ForEachAsync<TSource>(this IAsyncEnumerable<TSource> source, Action<TSource, int> action, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (action == null)
+                throw new ArgumentNullException(nameof(action));
+
+            return ForEachAsync_(source, action, cancellationToken);
+        }
+
+        private static async Task ForEachAsync_<TSource>(IAsyncEnumerable<TSource> source, Action<TSource, int> action, CancellationToken cancellationToken)
+        {
+            var index = 0;
+            using (var e = source.GetEnumerator())
+            {
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    action(e.Current, checked(index++));
+                }
+            }
+        }
+    }
+}

+ 62 - 0
Ix.NET/Source/System.Interactive.Async/Generate.cs

@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TResult> Generate<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector)
+        {
+            if (condition == null)
+                throw new ArgumentNullException(nameof(condition));
+            if (iterate == null)
+                throw new ArgumentNullException(nameof(iterate));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+
+            return Create(() =>
+                          {
+                              var i = initialState;
+                              var started = false;
+                              var current = default(TResult);
+
+                              return Create(
+                                  ct =>
+                                  {
+                                      var b = false;
+                                      try
+                                      {
+                                          if (started)
+                                              i = iterate(i);
+
+                                          b = condition(i);
+
+                                          if (b)
+                                              current = resultSelector(i);
+                                      }
+                                      catch (Exception ex)
+                                      {
+                                          return TaskExt.Throw<bool>(ex);
+                                      }
+
+                                      if (!b)
+                                          return TaskExt.False;
+
+                                      if (!started)
+                                          started = true;
+
+                                      return TaskExt.True;
+                                  },
+                                  () => current,
+                                  () => { }
+                              );
+                          });
+        }
+    }
+}

+ 180 - 0
Ix.NET/Source/System.Interactive.Async/GroupJoin.cs

@@ -0,0 +1,180 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IAsyncEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
+        {
+            if (outer == null)
+                throw new ArgumentNullException(nameof(outer));
+            if (inner == null)
+                throw new ArgumentNullException(nameof(inner));
+            if (outerKeySelector == null)
+                throw new ArgumentNullException(nameof(outerKeySelector));
+            if (innerKeySelector == null)
+                throw new ArgumentNullException(nameof(innerKeySelector));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+
+            return new GroupJoinAsyncEnumerable<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
+        }
+
+
+        public static IAsyncEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IAsyncEnumerable<TInner>, TResult> resultSelector)
+        {
+            if (outer == null)
+                throw new ArgumentNullException(nameof(outer));
+            if (inner == null)
+                throw new ArgumentNullException(nameof(inner));
+            if (outerKeySelector == null)
+                throw new ArgumentNullException(nameof(outerKeySelector));
+            if (innerKeySelector == null)
+                throw new ArgumentNullException(nameof(innerKeySelector));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+
+            return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
+        }
+
+        private sealed class AsyncEnumerableAdapter<T> : IAsyncEnumerable<T>
+        {
+            private readonly IEnumerable<T> _source;
+
+            public AsyncEnumerableAdapter(IEnumerable<T> source)
+            {
+                _source = source;
+            }
+
+            public IAsyncEnumerator<T> GetEnumerator()
+                => new AsyncEnumeratorAdapter(_source.GetEnumerator());
+
+            private sealed class AsyncEnumeratorAdapter : IAsyncEnumerator<T>
+            {
+                private readonly IEnumerator<T> _enumerator;
+
+                public AsyncEnumeratorAdapter(IEnumerator<T> enumerator)
+                {
+                    _enumerator = enumerator;
+                }
+
+                public Task<bool> MoveNext(CancellationToken cancellationToken)
+                {
+                    cancellationToken.ThrowIfCancellationRequested();
+
+#if HAS_AWAIT
+                    return Task.FromResult(_enumerator.MoveNext());
+#else
+                    return TaskEx.FromResult(_enumerator.MoveNext());
+#endif
+                }
+
+                public T Current => _enumerator.Current;
+
+                public void Dispose() => _enumerator.Dispose();
+            }
+        }
+
+
+        private sealed class GroupJoinAsyncEnumerable<TOuter, TInner, TKey, TResult> : IAsyncEnumerable<TResult>
+        {
+            private readonly IEqualityComparer<TKey> _comparer;
+            private readonly IAsyncEnumerable<TInner> _inner;
+            private readonly Func<TInner, TKey> _innerKeySelector;
+            private readonly IAsyncEnumerable<TOuter> _outer;
+            private readonly Func<TOuter, TKey> _outerKeySelector;
+            private readonly Func<TOuter, IAsyncEnumerable<TInner>, TResult> _resultSelector;
+
+            public GroupJoinAsyncEnumerable(
+                IAsyncEnumerable<TOuter> outer,
+                IAsyncEnumerable<TInner> inner,
+                Func<TOuter, TKey> outerKeySelector,
+                Func<TInner, TKey> innerKeySelector,
+                Func<TOuter, IAsyncEnumerable<TInner>, TResult> resultSelector,
+                IEqualityComparer<TKey> comparer)
+            {
+                _outer = outer;
+                _inner = inner;
+                _outerKeySelector = outerKeySelector;
+                _innerKeySelector = innerKeySelector;
+                _resultSelector = resultSelector;
+                _comparer = comparer;
+            }
+
+            public IAsyncEnumerator<TResult> GetEnumerator()
+                => new GroupJoinAsyncEnumerator(
+                    _outer.GetEnumerator(),
+                    _inner,
+                    _outerKeySelector,
+                    _innerKeySelector,
+                    _resultSelector,
+                    _comparer);
+
+            private sealed class GroupJoinAsyncEnumerator : IAsyncEnumerator<TResult>
+            {
+                private readonly IEqualityComparer<TKey> _comparer;
+                private readonly IAsyncEnumerable<TInner> _inner;
+                private readonly Func<TInner, TKey> _innerKeySelector;
+                private readonly IAsyncEnumerator<TOuter> _outer;
+                private readonly Func<TOuter, TKey> _outerKeySelector;
+                private readonly Func<TOuter, IAsyncEnumerable<TInner>, TResult> _resultSelector;
+
+                private Internal.Lookup<TKey, TInner> _lookup;
+
+                public GroupJoinAsyncEnumerator(
+                    IAsyncEnumerator<TOuter> outer,
+                    IAsyncEnumerable<TInner> inner,
+                    Func<TOuter, TKey> outerKeySelector,
+                    Func<TInner, TKey> innerKeySelector,
+                    Func<TOuter, IAsyncEnumerable<TInner>, TResult> resultSelector,
+                    IEqualityComparer<TKey> comparer)
+                {
+                    _outer = outer;
+                    _inner = inner;
+                    _outerKeySelector = outerKeySelector;
+                    _innerKeySelector = innerKeySelector;
+                    _resultSelector = resultSelector;
+                    _comparer = comparer;
+                }
+
+                public async Task<bool> MoveNext(CancellationToken cancellationToken)
+                {
+                    // nothing to do 
+                    if (!await _outer.MoveNext(cancellationToken)
+                                     .ConfigureAwait(false))
+                    {
+                        return false;
+                    }
+
+                    if (_lookup == null)
+                    {
+                        _lookup = await Internal.Lookup<TKey, TInner>.CreateForJoinAsync(_inner, _innerKeySelector, _comparer, cancellationToken)
+                                                .ConfigureAwait(false);
+                    }
+
+                    var item = _outer.Current;
+                    Current = _resultSelector(item, new AsyncEnumerableAdapter<TInner>(_lookup[_outerKeySelector(item)]));
+                    return true;
+                }
+
+                public TResult Current { get; private set; }
+
+                public void Dispose()
+                {
+                    _outer.Dispose();
+                }
+            }
+        }
+    }
+}

+ 348 - 24
Ix.NET/Source/System.Interactive.Async/Grouping.cs

@@ -1,48 +1,356 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the Apache 2.0 License.
 // See the LICENSE file in the project root for more information. 
+
+using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.ExceptionServices;
+using System.Threading;
+using System.Threading.Tasks;
 
-namespace System.Linq.Internal
+namespace System.Linq
 {
-    /// Adapted from System.Linq.Grouping from .NET Framework
-    /// Source: https://github.com/dotnet/corefx/blob/b90532bc97b07234a7d18073819d019645285f1c/src/System.Linq/src/System/Linq/Grouping.cs#L64
-    internal class Grouping<TKey, TElement> : IGrouping<TKey, TElement>, IList<TElement>
+    public static partial class AsyncEnumerable
     {
-        internal TKey _key;
-        internal int _hashCode;
-        internal TElement[] _elements;
-        internal int _count;
-        internal Grouping<TKey, TElement> _hashNext;
-        internal Grouping<TKey, TElement> _next;
+        public static IAsyncEnumerable<IAsyncGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (elementSelector == null)
+                throw new ArgumentNullException(nameof(elementSelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Create(() =>
+                          {
+                              var gate = new object();
+
+                              var e = source.GetEnumerator();
+                              var count = 1;
+
+                              var map = new Dictionary<TKey, AsyncGrouping<TKey, TElement>>(comparer);
+                              var list = new List<IAsyncGrouping<TKey, TElement>>();
+
+                              var index = 0;
+
+                              var current = default(IAsyncGrouping<TKey, TElement>);
+                              var faulted = default(ExceptionDispatchInfo);
+
+                              var res = default(bool?);
+
+                              var cts = new CancellationTokenDisposable();
+                              var refCount = new Disposable(
+                                  () =>
+                                  {
+                                      if (Interlocked.Decrement(ref count) == 0)
+                                          e.Dispose();
+                                  }
+                              );
+                              var d = Disposable.Create(cts, refCount);
+
+                              var iterateSource = default(Func<CancellationToken, Task<bool>>);
+                              iterateSource = async ct =>
+                                              {
+                                                  lock (gate)
+                                                  {
+                                                      if (res != null)
+                                                      {
+                                                          return res.Value;
+                                                      }
+                                                      res = null;
+                                                  }
+
+                                                  faulted?.Throw();
+
+                                                  try
+                                                  {
+                                                      res = await e.MoveNext(ct)
+                                                                   .ConfigureAwait(false);
+                                                      if (res == true)
+                                                      {
+                                                          var key = default(TKey);
+                                                          var element = default(TElement);
+
+                                                          var cur = e.Current;
+                                                          try
+                                                          {
+                                                              key = keySelector(cur);
+                                                              element = elementSelector(cur);
+                                                          }
+                                                          catch (Exception exception)
+                                                          {
+                                                              foreach (var v in map.Values)
+                                                                  v.Error(exception);
+
+                                                              throw;
+                                                          }
+
+                                                          var group = default(AsyncGrouping<TKey, TElement>);
+                                                          if (!map.TryGetValue(key, out group))
+                                                          {
+                                                              group = new AsyncGrouping<TKey, TElement>(key, iterateSource, refCount);
+                                                              map.Add(key, group);
+                                                              lock (list)
+                                                                  list.Add(group);
+
+                                                              Interlocked.Increment(ref count);
+                                                          }
+                                                          group.Add(element);
+                                                      }
+
+                                                      return res.Value;
+                                                  }
+                                                  catch (Exception ex)
+                                                  {
+                                                      foreach (var v in map.Values)
+                                                          v.Error(ex);
+
+                                                      faulted = ExceptionDispatchInfo.Capture(ex);
+                                                      throw;
+                                                  }
+                                                  finally
+                                                  {
+                                                      res = null;
+                                                  }
+                                              };
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      var result = await iterateSource(ct)
+                                                       .ConfigureAwait(false);
 
-        internal Grouping()
+                                      current = null;
+                                      lock (list)
+                                      {
+                                          if (index < list.Count)
+                                              current = list[index++];
+                                      }
+
+                                      if (current != null)
+                                      {
+                                          return true;
+                                      }
+                                      return result && await f(ct)
+                                                 .ConfigureAwait(false);
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<IAsyncGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
         {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (elementSelector == null)
+                throw new ArgumentNullException(nameof(elementSelector));
+
+            return source.GroupBy(keySelector, elementSelector, EqualityComparer<TKey>.Default);
         }
 
-        internal void Add(TElement element)
+        public static IAsyncEnumerable<IAsyncGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
         {
-            if (_elements.Length == _count)
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.GroupBy(keySelector, x => x, comparer);
+        }
+
+        public static IAsyncEnumerable<IAsyncGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.GroupBy(keySelector, x => x, EqualityComparer<TKey>.Default);
+        }
+
+        public static IAsyncEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IAsyncEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (elementSelector == null)
+                throw new ArgumentNullException(nameof(elementSelector));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.GroupBy(keySelector, elementSelector, comparer)
+                         .Select(g => resultSelector(g.Key, g));
+        }
+
+        public static IAsyncEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IAsyncEnumerable<TElement>, TResult> resultSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (elementSelector == null)
+                throw new ArgumentNullException(nameof(elementSelector));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+
+            return source.GroupBy(keySelector, elementSelector, EqualityComparer<TKey>.Default)
+                         .Select(g => resultSelector(g.Key, g));
+        }
+
+        public static IAsyncEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IAsyncEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.GroupBy(keySelector, x => x, comparer)
+                         .Select(g => resultSelector(g.Key, g));
+        }
+
+        public static IAsyncEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IAsyncEnumerable<TSource>, TResult> resultSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+
+            return source.GroupBy(keySelector, x => x, EqualityComparer<TKey>.Default)
+                         .Select(g => resultSelector(g.Key, g));
+        }
+
+        private static IEnumerable<IGrouping<TKey, TElement>> GroupUntil<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IComparer<TKey> comparer)
+        {
+            var group = default(EnumerableGrouping<TKey, TElement>);
+            foreach (var x in source)
             {
-                Array.Resize(ref _elements, checked(_count * 2));
+                var key = keySelector(x);
+                if (group == null || comparer.Compare(group.Key, key) != 0)
+                {
+                    group = new EnumerableGrouping<TKey, TElement>(key);
+                    yield return group;
+                }
+                group.Add(elementSelector(x));
             }
-
-            _elements[_count] = element;
-            _count++;
         }
 
-        internal void Trim()
+        private class AsyncGrouping<TKey, TElement> : IAsyncGrouping<TKey, TElement>
         {
-            if (_elements.Length != _count)
+            private readonly List<TElement> elements = new List<TElement>();
+            private readonly Func<CancellationToken, Task<bool>> iterateSource;
+            private readonly IDisposable sourceDisposable;
+            private bool done;
+            private ExceptionDispatchInfo exception;
+
+            public AsyncGrouping(TKey key, Func<CancellationToken, Task<bool>> iterateSource, IDisposable sourceDisposable)
             {
-                Array.Resize(ref _elements, _count);
+                this.iterateSource = iterateSource;
+                this.sourceDisposable = sourceDisposable;
+                Key = key;
+            }
+
+            public TKey Key { get; }
+
+            public IAsyncEnumerator<TElement> GetEnumerator()
+            {
+                var index = -1;
+
+                var cts = new CancellationTokenDisposable();
+                var d = Disposable.Create(cts, sourceDisposable);
+
+                var f = default(Func<CancellationToken, Task<bool>>);
+                f = async ct =>
+                    {
+                        var size = 0;
+                        lock (elements)
+                            size = elements.Count;
+
+                        if (index < size)
+                        {
+                            return true;
+                        }
+                        if (done)
+                        {
+                            exception?.Throw();
+                            return false;
+                        }
+                        if (await iterateSource(ct)
+                                .ConfigureAwait(false))
+                        {
+                            return await f(ct)
+                                       .ConfigureAwait(false);
+                        }
+                        return false;
+                    };
+
+                return Create(
+                    ct =>
+                    {
+                        ++index;
+                        return f(cts.Token);
+                    },
+                    () => elements[index],
+                    d.Dispose,
+                    null
+                );
+            }
+
+            public void Add(TElement element)
+            {
+                lock (elements)
+                    elements.Add(element);
+            }
+
+            public void Error(Exception exception)
+            {
+                done = true;
+                this.exception = ExceptionDispatchInfo.Capture(exception);
             }
         }
+    }
+}
+
+// Note: The type here has to be internal as System.Linq has it's own public copy we're not using
+
+namespace System.Linq.Internal
+{
+    /// Adapted from System.Linq.Grouping from .NET Framework
+    /// Source: https://github.com/dotnet/corefx/blob/b90532bc97b07234a7d18073819d019645285f1c/src/System.Linq/src/System/Linq/Grouping.cs#L64
+    internal class Grouping<TKey, TElement> : IGrouping<TKey, TElement>, IList<TElement>
+    {
+        internal int _count;
+        internal TElement[] _elements;
+        internal int _hashCode;
+        internal Grouping<TKey, TElement> _hashNext;
+        internal TKey _key;
+        internal Grouping<TKey, TElement> _next;
 
         public IEnumerator<TElement> GetEnumerator()
         {
-            for (int i = 0; i < _count; i++)
+            for (var i = 0; i < _count; i++)
             {
                 yield return _elements[i];
             }
@@ -122,10 +430,26 @@ namespace System.Linq.Internal
                 return _elements[index];
             }
 
-            set
+            set { throw new NotSupportedException(Strings.NOT_SUPPORTED); }
+        }
+
+        internal void Add(TElement element)
+        {
+            if (_elements.Length == _count)
+            {
+                Array.Resize(ref _elements, checked(_count*2));
+            }
+
+            _elements[_count] = element;
+            _count++;
+        }
+
+        internal void Trim()
+        {
+            if (_elements.Length != _count)
             {
-                throw new NotSupportedException(Strings.NOT_SUPPORTED);
+                Array.Resize(ref _elements, _count);
             }
         }
     }
-}
+}

+ 49 - 0
Ix.NET/Source/System.Interactive.Async/IgnoreElements.cs

@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> IgnoreElements<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (!await e.MoveNext(ct)
+                                                  .ConfigureAwait(false))
+                                      {
+                                          return false;
+                                      }
+
+                                      return await f(ct)
+                                                 .ConfigureAwait(false);
+                                  };
+
+                              return Create<TSource>(
+                                  f,
+                                  () => { throw new InvalidOperationException(); },
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 77 - 0
Ix.NET/Source/System.Interactive.Async/Intersect.cs

@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Intersect<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Create(() =>
+                          {
+                              var e = first.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var mapTask = default(Task<Dictionary<TSource, TSource>>);
+                              var getMapTask = new Func<CancellationToken, Task<Dictionary<TSource, TSource>>>(
+                                  ct =>
+                                  {
+                                      if (mapTask == null)
+                                          mapTask = second.ToDictionary(x => x, comparer, ct);
+                                      return mapTask;
+                                  });
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (await e.MoveNext(ct)
+                                                 .Zip(getMapTask(ct), (b, _) => b)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          // Note: Result here is safe because the task
+                                          // was completed in the Zip() call above
+                                          if (mapTask.Result.ContainsKey(e.Current))
+                                              return true;
+                                          return await f(ct)
+                                                     .ConfigureAwait(false);
+                                      }
+                                      return false;
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => e.Current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+
+        public static IAsyncEnumerable<TSource> Intersect<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            return first.Intersect(second, EqualityComparer<TSource>.Default);
+        }
+    }
+}

+ 175 - 0
Ix.NET/Source/System.Interactive.Async/Join.cs

@@ -0,0 +1,175 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
+        {
+            if (outer == null)
+                throw new ArgumentNullException(nameof(outer));
+            if (inner == null)
+                throw new ArgumentNullException(nameof(inner));
+            if (outerKeySelector == null)
+                throw new ArgumentNullException(nameof(outerKeySelector));
+            if (innerKeySelector == null)
+                throw new ArgumentNullException(nameof(innerKeySelector));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Create(
+                () =>
+                {
+                    var oe = outer.GetEnumerator();
+                    var ie = inner.GetEnumerator();
+
+                    var cts = new CancellationTokenDisposable();
+                    var d = Disposable.Create(cts, oe, ie);
+
+                    var current = default(TResult);
+                    var useOuter = true;
+                    var outerMap = new Dictionary<TKey, List<TOuter>>(comparer);
+                    var innerMap = new Dictionary<TKey, List<TInner>>(comparer);
+                    var q = new Queue<TResult>();
+
+                    var f = default(Func<CancellationToken, Task<bool>>);
+                    f = async ct =>
+                        {
+                            if (q.Count > 0)
+                            {
+                                current = q.Dequeue();
+                                return true;
+                            }
+
+                            var b = useOuter;
+                            if (ie == null && oe == null)
+                            {
+                                return false;
+                            }
+                            if (ie == null)
+                                b = true;
+                            else if (oe == null)
+                                b = false;
+                            useOuter = !useOuter;
+
+                            var enqueue = new Func<TOuter, TInner, bool>(
+                                (o, i) =>
+                                {
+                                    var result = resultSelector(o, i);
+                                    q.Enqueue(result);
+                                    return true;
+                                });
+
+                            if (b)
+                            {
+                                if (await oe.MoveNext(ct)
+                                            .ConfigureAwait(false))
+                                {
+                                    var element = oe.Current;
+                                    var key = default(TKey);
+
+                                    key = outerKeySelector(element);
+
+                                    var outerList = default(List<TOuter>);
+                                    if (!outerMap.TryGetValue(key, out outerList))
+                                    {
+                                        outerList = new List<TOuter>();
+                                        outerMap.Add(key, outerList);
+                                    }
+
+                                    outerList.Add(element);
+
+                                    var innerList = default(List<TInner>);
+                                    if (!innerMap.TryGetValue(key, out innerList))
+                                    {
+                                        innerList = new List<TInner>();
+                                        innerMap.Add(key, innerList);
+                                    }
+
+                                    foreach (var v in innerList)
+                                    {
+                                        if (!enqueue(element, v))
+                                            return false;
+                                    }
+
+                                    return await f(ct)
+                                               .ConfigureAwait(false);
+                                }
+                                oe.Dispose();
+                                oe = null;
+                                return await f(ct)
+                                           .ConfigureAwait(false);
+                            }
+                            if (await ie.MoveNext(ct)
+                                        .ConfigureAwait(false))
+                            {
+                                var element = ie.Current;
+                                var key = innerKeySelector(element);
+
+                                var innerList = default(List<TInner>);
+                                if (!innerMap.TryGetValue(key, out innerList))
+                                {
+                                    innerList = new List<TInner>();
+                                    innerMap.Add(key, innerList);
+                                }
+
+                                innerList.Add(element);
+
+                                var outerList = default(List<TOuter>);
+                                if (!outerMap.TryGetValue(key, out outerList))
+                                {
+                                    outerList = new List<TOuter>();
+                                    outerMap.Add(key, outerList);
+                                }
+
+                                foreach (var v in outerList)
+                                {
+                                    if (!enqueue(v, element))
+                                        return false;
+                                }
+
+                                return await f(ct)
+                                           .ConfigureAwait(false);
+                            }
+                            ie.Dispose();
+                            ie = null;
+                            return await f(ct)
+                                       .ConfigureAwait(false);
+                        };
+
+                    return Create(
+                        f,
+                        () => current,
+                        d.Dispose,
+                        ie
+                    );
+                });
+        }
+
+        public static IAsyncEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(this IAsyncEnumerable<TOuter> outer, IAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector)
+        {
+            if (outer == null)
+                throw new ArgumentNullException(nameof(outer));
+            if (inner == null)
+                throw new ArgumentNullException(nameof(inner));
+            if (outerKeySelector == null)
+                throw new ArgumentNullException(nameof(outerKeySelector));
+            if (innerKeySelector == null)
+                throw new ArgumentNullException(nameof(innerKeySelector));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+
+            return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
+        }
+    }
+}

+ 125 - 0
Ix.NET/Source/System.Interactive.Async/Last.cs

@@ -0,0 +1,125 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<TSource> Last<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Last(source, CancellationToken.None);
+        }
+
+        public static Task<TSource> Last<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (predicate == null)
+                throw new ArgumentNullException("predicate");
+
+            return Last(source, predicate, CancellationToken.None);
+        }
+
+        public static Task<TSource> Last<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Last_(source, cancellationToken);
+        }
+
+        public static Task<TSource> Last<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return source.Where(predicate)
+                         .Last(cancellationToken);
+        }
+
+        public static Task<TSource> LastOrDefault<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return LastOrDefault(source, CancellationToken.None);
+        }
+
+        public static Task<TSource> LastOrDefault<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (predicate == null)
+                throw new ArgumentNullException("predicate");
+
+            return LastOrDefault(source, predicate, CancellationToken.None);
+        }
+
+        public static Task<TSource> LastOrDefault<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return LastOrDefault_(source, cancellationToken);
+        }
+
+        public static Task<TSource> LastOrDefault<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return source.Where(predicate)
+                         .LastOrDefault(cancellationToken);
+        }
+
+        private static async Task<TSource> Last_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            var last = default(TSource);
+            var hasLast = false;
+
+            using (var e = source.GetEnumerator())
+            {
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    hasLast = true;
+                    last = e.Current;
+                }
+            }
+            if (!hasLast)
+                throw new InvalidOperationException(Strings.NO_ELEMENTS);
+            return last;
+        }
+
+        private static async Task<TSource> LastOrDefault_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            var last = default(TSource);
+            var hasLast = false;
+
+            using (var e = source.GetEnumerator())
+            {
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    hasLast = true;
+                    last = e.Current;
+                }
+            }
+            return !hasLast ? default(TSource) : last;
+        }
+    }
+}

+ 229 - 123
Ix.NET/Source/System.Interactive.Async/Lookup.cs

@@ -1,102 +1,130 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the Apache 2.0 License.
 // See the LICENSE file in the project root for more information. 
+
+using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 
-namespace System.Linq.Internal
+
+namespace System.Linq
 {
-    internal class Lookup<TKey, TElement> : ILookup<TKey, TElement>
+    public static partial class AsyncEnumerable
     {
-        private readonly IEqualityComparer<TKey> _comparer;
-        private Grouping<TKey, TElement>[] _groupings;
-        private Grouping<TKey, TElement> _lastGrouping;
-        private int _count;
-
-        internal static Lookup<TKey, TElement> Create<TSource>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
+        public static Task<ILookup<TKey, TElement>> ToLookup<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
         {
-            Debug.Assert(source != null);
-            Debug.Assert(keySelector != null);
-            Debug.Assert(elementSelector != null);
-
-            Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
-            foreach (TSource item in source)
-            {
-                lookup.GetGrouping(keySelector(item), create: true).Add(elementSelector(item));
-            }
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (keySelector == null)
+                throw new ArgumentNullException("keySelector");
+            if (elementSelector == null)
+                throw new ArgumentNullException("elementSelector");
+            if (comparer == null)
+                throw new ArgumentNullException("comparer");
+
+            return ToLookup(source, keySelector, elementSelector, comparer, CancellationToken.None);
+        }
 
-            return lookup;
+        public static Task<ILookup<TKey, TElement>> ToLookup<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (keySelector == null)
+                throw new ArgumentNullException("keySelector");
+            if (elementSelector == null)
+                throw new ArgumentNullException("elementSelector");
+
+            return ToLookup(source, keySelector, elementSelector, CancellationToken.None);
         }
 
-        internal static async Task<Lookup<TKey, TElement>> CreateAsync<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
+        public static Task<ILookup<TKey, TSource>> ToLookup<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
         {
-            Debug.Assert(source != null);
-            Debug.Assert(keySelector != null);
-            Debug.Assert(elementSelector != null);
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (keySelector == null)
+                throw new ArgumentNullException("keySelector");
+            if (comparer == null)
+                throw new ArgumentNullException("comparer");
+
+            return ToLookup(source, keySelector, comparer, CancellationToken.None);
+        }
 
-            Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
-            using (var enu = source.GetEnumerator())
-            {
-                while (await enu.MoveNext(cancellationToken)
-                                .ConfigureAwait(false))
-                {
-                    lookup.GetGrouping(keySelector(enu.Current), create: true).Add(elementSelector(enu.Current));
-                }
-            }
+        public static Task<ILookup<TKey, TSource>> ToLookup<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (keySelector == null)
+                throw new ArgumentNullException("keySelector");
 
-            return lookup;
+            return ToLookup(source, keySelector, CancellationToken.None);
         }
 
-        internal static Lookup<TKey, TElement> Create(IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        public static async Task<ILookup<TKey, TElement>> ToLookup<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
         {
-            Debug.Assert(source != null);
-            Debug.Assert(keySelector != null);
-
-            Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
-            foreach (TElement item in source)
-            {
-                lookup.GetGrouping(keySelector(item), create: true).Add(item);
-            }
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (elementSelector == null)
+                throw new ArgumentNullException(nameof(elementSelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            var lookup = await Internal.Lookup<TKey, TElement>.CreateAsync(source, keySelector, elementSelector, comparer, cancellationToken)
+                                       .ConfigureAwait(false);
 
             return lookup;
         }
 
-        internal static Lookup<TKey, TElement> CreateForJoin(IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        public static Task<ILookup<TKey, TElement>> ToLookup<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, CancellationToken cancellationToken)
         {
-            Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
-            foreach (TElement item in source)
-            {
-                TKey key = keySelector(item);
-                if (key != null)
-                {
-                    lookup.GetGrouping(key, create: true).Add(item);
-                }
-            }
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (elementSelector == null)
+                throw new ArgumentNullException(nameof(elementSelector));
+
+            return source.ToLookup(keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
+        }
 
-            return lookup;
+        public static Task<ILookup<TKey, TSource>> ToLookup<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.ToLookup(keySelector, x => x, comparer, cancellationToken);
         }
 
-        internal static async Task<Lookup<TKey, TElement>> CreateForJoinAsync(IAsyncEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
+        public static Task<ILookup<TKey, TSource>> ToLookup<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken)
         {
-            Lookup<TKey, TElement> lookup = new Lookup<TKey, TElement>(comparer);
-            using (var enu = source.GetEnumerator())
-            {
-                while (await enu.MoveNext(cancellationToken)
-                                .ConfigureAwait(false))
-                {
-                    TKey key = keySelector(enu.Current);
-                    if (key != null)
-                    {
-                        lookup.GetGrouping(key, create: true).Add(enu.Current);
-                    }
-                }
-            }
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
 
-            return lookup;
+            return source.ToLookup(keySelector, x => x, EqualityComparer<TKey>.Default, cancellationToken);
         }
+    }
+}
+
+// This is internal because System.Linq exposes a public Lookup that we cannot directly use here
+
+namespace System.Linq.Internal
+{
+    internal class Lookup<TKey, TElement> : ILookup<TKey, TElement>
+    {
+        private readonly IEqualityComparer<TKey> _comparer;
+        private Grouping<TKey, TElement>[] _groupings;
+        private Grouping<TKey, TElement> _lastGrouping;
 
         private Lookup(IEqualityComparer<TKey> comparer)
         {
@@ -104,16 +132,13 @@ namespace System.Linq.Internal
             _groupings = new Grouping<TKey, TElement>[7];
         }
 
-        public int Count
-        {
-            get { return _count; }
-        }
+        public int Count { get; private set; }
 
         public IEnumerable<TElement> this[TKey key]
         {
             get
             {
-                Grouping<TKey, TElement> grouping = GetGrouping(key, create: false);
+                var grouping = GetGrouping(key, create: false);
                 if (grouping != null)
                 {
                     return grouping;
@@ -134,87 +159,127 @@ namespace System.Linq.Internal
 
         public IEnumerator<IGrouping<TKey, TElement>> GetEnumerator()
         {
-            Grouping<TKey, TElement> g = _lastGrouping;
+            var g = _lastGrouping;
             if (g != null)
             {
                 do
                 {
                     g = g._next;
                     yield return g;
-                }
-                while (g != _lastGrouping);
+                } while (g != _lastGrouping);
             }
         }
 
-        internal TResult[] ToArray<TResult>(Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+
+        public IEnumerable<TResult> ApplyResultSelector<TResult>(Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
         {
-            TResult[] array = new TResult[_count];
-            int index = 0;
-            Grouping<TKey, TElement> g = _lastGrouping;
+            var g = _lastGrouping;
             if (g != null)
             {
                 do
                 {
                     g = g._next;
                     g.Trim();
-                    array[index] = resultSelector(g._key, g._elements);
-                    ++index;
-                }
-                while (g != _lastGrouping);
+                    yield return resultSelector(g._key, g._elements);
+                } while (g != _lastGrouping);
             }
+        }
 
-            return array;
+        internal static Lookup<TKey, TElement> Create<TSource>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
+        {
+            Debug.Assert(source != null);
+            Debug.Assert(keySelector != null);
+            Debug.Assert(elementSelector != null);
+
+            var lookup = new Lookup<TKey, TElement>(comparer);
+            foreach (var item in source)
+            {
+                lookup.GetGrouping(keySelector(item), create: true)
+                      .Add(elementSelector(item));
+            }
+
+            return lookup;
         }
 
+        internal static Lookup<TKey, TElement> Create(IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            Debug.Assert(source != null);
+            Debug.Assert(keySelector != null);
 
-        internal List<TResult> ToList<TResult>(Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
+            var lookup = new Lookup<TKey, TElement>(comparer);
+            foreach (var item in source)
+            {
+                lookup.GetGrouping(keySelector(item), create: true)
+                      .Add(item);
+            }
+
+            return lookup;
+        }
+
+        internal static async Task<Lookup<TKey, TElement>> CreateAsync<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
         {
-            List<TResult> list = new List<TResult>(_count);
-            Grouping<TKey, TElement> g = _lastGrouping;
-            if (g != null)
+            Debug.Assert(source != null);
+            Debug.Assert(keySelector != null);
+            Debug.Assert(elementSelector != null);
+
+            var lookup = new Lookup<TKey, TElement>(comparer);
+            using (var enu = source.GetEnumerator())
             {
-                do
+                while (await enu.MoveNext(cancellationToken)
+                                .ConfigureAwait(false))
                 {
-                    g = g._next;
-                    g.Trim();
-                    list.Add(resultSelector(g._key, g._elements));
+                    lookup.GetGrouping(keySelector(enu.Current), create: true)
+                          .Add(elementSelector(enu.Current));
                 }
-                while (g != _lastGrouping);
             }
 
-            return list;
+            return lookup;
         }
 
-        public IEnumerable<TResult> ApplyResultSelector<TResult>(Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
+        internal static Lookup<TKey, TElement> CreateForJoin(IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer)
         {
-            Grouping<TKey, TElement> g = _lastGrouping;
-            if (g != null)
+            var lookup = new Lookup<TKey, TElement>(comparer);
+            foreach (var item in source)
             {
-                do
+                var key = keySelector(item);
+                if (key != null)
                 {
-                    g = g._next;
-                    g.Trim();
-                    yield return resultSelector(g._key, g._elements);
+                    lookup.GetGrouping(key, create: true)
+                          .Add(item);
                 }
-                while (g != _lastGrouping);
             }
-        }
 
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return GetEnumerator();
+            return lookup;
         }
 
-        internal int InternalGetHashCode(TKey key)
+        internal static async Task<Lookup<TKey, TElement>> CreateForJoinAsync(IAsyncEnumerable<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
         {
-            // Handle comparer implementations that throw when passed null
-            return (key == null) ? 0 : _comparer.GetHashCode(key) & 0x7FFFFFFF;
+            var lookup = new Lookup<TKey, TElement>(comparer);
+            using (var enu = source.GetEnumerator())
+            {
+                while (await enu.MoveNext(cancellationToken)
+                                .ConfigureAwait(false))
+                {
+                    var key = keySelector(enu.Current);
+                    if (key != null)
+                    {
+                        lookup.GetGrouping(key, create: true)
+                              .Add(enu.Current);
+                    }
+                }
+            }
+
+            return lookup;
         }
 
         internal Grouping<TKey, TElement> GetGrouping(TKey key, bool create)
         {
-            int hashCode = InternalGetHashCode(key);
-            for (Grouping<TKey, TElement> g = _groupings[hashCode % _groupings.Length]; g != null; g = g._hashNext)
+            var hashCode = InternalGetHashCode(key);
+            for (var g = _groupings[hashCode%_groupings.Length]; g != null; g = g._hashNext)
             {
                 if (g._hashCode == hashCode && _comparer.Equals(g._key, key))
                 {
@@ -224,13 +289,13 @@ namespace System.Linq.Internal
 
             if (create)
             {
-                if (_count == _groupings.Length)
+                if (Count == _groupings.Length)
                 {
                     Resize();
                 }
 
-                int index = hashCode % _groupings.Length;
-                Grouping<TKey, TElement> g = new Grouping<TKey, TElement>();
+                var index = hashCode%_groupings.Length;
+                var g = new Grouping<TKey, TElement>();
                 g._key = key;
                 g._hashCode = hashCode;
                 g._elements = new TElement[1];
@@ -247,29 +312,70 @@ namespace System.Linq.Internal
                 }
 
                 _lastGrouping = g;
-                _count++;
+                Count++;
                 return g;
             }
 
             return null;
         }
 
+        internal int InternalGetHashCode(TKey key)
+        {
+            // Handle comparer implementations that throw when passed null
+            return (key == null) ? 0 : _comparer.GetHashCode(key) & 0x7FFFFFFF;
+        }
+
+        internal TResult[] ToArray<TResult>(Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
+        {
+            var array = new TResult[Count];
+            var index = 0;
+            var g = _lastGrouping;
+            if (g != null)
+            {
+                do
+                {
+                    g = g._next;
+                    g.Trim();
+                    array[index] = resultSelector(g._key, g._elements);
+                    ++index;
+                } while (g != _lastGrouping);
+            }
+
+            return array;
+        }
+
+
+        internal List<TResult> ToList<TResult>(Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
+        {
+            var list = new List<TResult>(Count);
+            var g = _lastGrouping;
+            if (g != null)
+            {
+                do
+                {
+                    g = g._next;
+                    g.Trim();
+                    list.Add(resultSelector(g._key, g._elements));
+                } while (g != _lastGrouping);
+            }
+
+            return list;
+        }
+
         private void Resize()
         {
-            int newSize = checked((_count * 2) + 1);
-            Grouping<TKey, TElement>[] newGroupings = new Grouping<TKey, TElement>[newSize];
-            Grouping<TKey, TElement> g = _lastGrouping;
+            var newSize = checked((Count*2) + 1);
+            var newGroupings = new Grouping<TKey, TElement>[newSize];
+            var g = _lastGrouping;
             do
             {
                 g = g._next;
-                int index = g._hashCode % newSize;
+                var index = g._hashCode%newSize;
                 g._hashNext = newGroupings[index];
                 newGroupings[index] = g;
-            }
-            while (g != _lastGrouping);
+            } while (g != _lastGrouping);
 
             _groupings = newGroupings;
         }
     }
-
-}
+}

+ 508 - 0
Ix.NET/Source/System.Interactive.Async/Max.cs

@@ -0,0 +1,508 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<TSource> Max<TSource>(this IAsyncEnumerable<TSource> source, IComparer<TSource> comparer, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Max_(source, comparer, cancellationToken);
+        }
+
+        public static Task<int> Max(this IAsyncEnumerable<int> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Max(source, CancellationToken.None);
+        }
+
+        public static Task<long> Max(this IAsyncEnumerable<long> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Max(source, CancellationToken.None);
+        }
+
+        public static Task<double> Max(this IAsyncEnumerable<double> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Max(source, CancellationToken.None);
+        }
+
+        public static Task<float> Max(this IAsyncEnumerable<float> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Max(source, CancellationToken.None);
+        }
+
+
+        public static Task<int> Max(this IAsyncEnumerable<int> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(Math.Max, cancellationToken);
+        }
+
+        public static Task<long> Max(this IAsyncEnumerable<long> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(Math.Max, cancellationToken);
+        }
+
+        public static Task<double> Max(this IAsyncEnumerable<double> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(Math.Max, cancellationToken);
+        }
+
+        public static Task<float> Max(this IAsyncEnumerable<float> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(Math.Max, cancellationToken);
+        }
+
+        public static Task<decimal> Max(this IAsyncEnumerable<decimal> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(Math.Max, cancellationToken);
+        }
+
+        public static Task<int?> Max(this IAsyncEnumerable<int?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(default(int?), NullableMax, cancellationToken);
+        }
+
+        public static Task<long?> Max(this IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(default(long?), NullableMax, cancellationToken);
+        }
+
+        public static Task<double?> Max(this IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(default(double?), NullableMax, cancellationToken);
+        }
+
+        public static Task<float?> Max(this IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(default(float?), NullableMax, cancellationToken);
+        }
+
+        public static Task<decimal?> Max(this IAsyncEnumerable<decimal?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(default(decimal?), NullableMax, cancellationToken);
+        }
+
+        public static Task<TSource> Max<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            var comparer = Comparer<TSource>.Default;
+            return source.Aggregate((x, y) => comparer.Compare(x, y) >= 0 ? x : y, cancellationToken);
+        }
+
+        public static Task<int> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Max(cancellationToken);
+        }
+
+        public static Task<long> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Max(cancellationToken);
+        }
+
+        public static Task<double> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Max(cancellationToken);
+        }
+
+        public static Task<float> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Max(cancellationToken);
+        }
+
+        public static Task<decimal> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Max(cancellationToken);
+        }
+
+        public static Task<int?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Max(cancellationToken);
+        }
+
+        public static Task<long?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Max(cancellationToken);
+        }
+
+        public static Task<double?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Max(cancellationToken);
+        }
+
+        public static Task<float?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Max(cancellationToken);
+        }
+
+        public static Task<decimal?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Max(cancellationToken);
+        }
+
+        public static Task<TResult> Max<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Max(cancellationToken);
+        }
+
+
+        public static Task<decimal> Max(this IAsyncEnumerable<decimal> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Max(source, CancellationToken.None);
+        }
+
+        public static Task<int?> Max(this IAsyncEnumerable<int?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Max(source, CancellationToken.None);
+        }
+
+        public static Task<long?> Max(this IAsyncEnumerable<long?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Max(source, CancellationToken.None);
+        }
+
+        public static Task<double?> Max(this IAsyncEnumerable<double?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Max(source, CancellationToken.None);
+        }
+
+        public static Task<float?> Max(this IAsyncEnumerable<float?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Max(source, CancellationToken.None);
+        }
+
+        public static Task<decimal?> Max(this IAsyncEnumerable<decimal?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Max(source, CancellationToken.None);
+        }
+
+        public static Task<TSource> Max<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Max(source, CancellationToken.None);
+        }
+
+        public static Task<int> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Max(source, selector, CancellationToken.None);
+        }
+
+        public static Task<long> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Max(source, selector, CancellationToken.None);
+        }
+
+        public static Task<double> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Max(source, selector, CancellationToken.None);
+        }
+
+        public static Task<float> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Max(source, selector, CancellationToken.None);
+        }
+
+        public static Task<decimal> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Max(source, selector, CancellationToken.None);
+        }
+
+        public static Task<int?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Max(source, selector, CancellationToken.None);
+        }
+
+        public static Task<long?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Max(source, selector, CancellationToken.None);
+        }
+
+        public static Task<double?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Max(source, selector, CancellationToken.None);
+        }
+
+        public static Task<float?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Max(source, selector, CancellationToken.None);
+        }
+
+        public static Task<decimal?> Max<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Max(source, selector, CancellationToken.None);
+        }
+
+        public static Task<TResult> Max<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Max(source, selector, CancellationToken.None);
+        }
+
+
+        public static Task<TSource> Max<TSource>(this IAsyncEnumerable<TSource> source, IComparer<TSource> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (comparer == null)
+                throw new ArgumentNullException("comparer");
+
+            return source.Max(comparer, CancellationToken.None);
+        }
+
+        public static Task<IList<TSource>> MaxBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (keySelector == null)
+                throw new ArgumentNullException("keySelector");
+
+            return source.MaxBy(keySelector, CancellationToken.None);
+        }
+
+        public static Task<IList<TSource>> MaxBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (keySelector == null)
+                throw new ArgumentNullException("keySelector");
+            if (comparer == null)
+                throw new ArgumentNullException("comparer");
+
+            return source.MaxBy(keySelector, comparer, CancellationToken.None);
+        }
+
+        public static Task<IList<TSource>> MaxBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return MaxBy(source, keySelector, Comparer<TKey>.Default, cancellationToken);
+        }
+
+        public static Task<IList<TSource>> MaxBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return ExtremaBy(source, keySelector, (key, minValue) => comparer.Compare(key, minValue), cancellationToken);
+        }
+
+        private static async Task<TSource> Max_<TSource>(IAsyncEnumerable<TSource> source, IComparer<TSource> comparer, CancellationToken cancellationToken)
+        {
+            return (await MaxBy(source, x => x, comparer, cancellationToken)
+                        .ConfigureAwait(false)).First();
+        }
+
+        private static T? NullableMax<T>(T? x, T? y)
+            where T : struct, IComparable<T>
+        {
+            if (!x.HasValue)
+                return y;
+            if (!y.HasValue)
+                return x;
+            if (x.Value.CompareTo(y.Value) >= 0)
+                return x;
+            return y;
+        }
+    }
+}

+ 549 - 0
Ix.NET/Source/System.Interactive.Async/Min.cs

@@ -0,0 +1,549 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<decimal?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Min(source, selector, CancellationToken.None);
+        }
+
+        public static Task<TResult> Min<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Min(source, selector, CancellationToken.None);
+        }
+
+        public static Task<TSource> Min<TSource>(this IAsyncEnumerable<TSource> source, IComparer<TSource> comparer, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return Min_(source, comparer, cancellationToken);
+        }
+
+
+        public static Task<int> Min(this IAsyncEnumerable<int> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Min(source, CancellationToken.None);
+        }
+
+        public static Task<long> Min(this IAsyncEnumerable<long> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Min(source, CancellationToken.None);
+        }
+
+        public static Task<double> Min(this IAsyncEnumerable<double> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Min(source, CancellationToken.None);
+        }
+
+        public static Task<float> Min(this IAsyncEnumerable<float> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Min(source, CancellationToken.None);
+        }
+
+        public static Task<decimal> Min(this IAsyncEnumerable<decimal> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Min(source, CancellationToken.None);
+        }
+
+        public static Task<int?> Min(this IAsyncEnumerable<int?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Min(source, CancellationToken.None);
+        }
+
+        public static Task<long?> Min(this IAsyncEnumerable<long?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Min(source, CancellationToken.None);
+        }
+
+        public static Task<double?> Min(this IAsyncEnumerable<double?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Min(source, CancellationToken.None);
+        }
+
+        public static Task<float?> Min(this IAsyncEnumerable<float?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Min(source, CancellationToken.None);
+        }
+
+        public static Task<decimal?> Min(this IAsyncEnumerable<decimal?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Min(source, CancellationToken.None);
+        }
+
+        public static Task<TSource> Min<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Min(source, CancellationToken.None);
+        }
+
+        public static Task<int> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Min(source, selector, CancellationToken.None);
+        }
+
+        public static Task<long> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Min(source, selector, CancellationToken.None);
+        }
+
+        public static Task<double> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Min(source, selector, CancellationToken.None);
+        }
+
+        public static Task<float> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Min(source, selector, CancellationToken.None);
+        }
+
+        public static Task<decimal> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Min(source, selector, CancellationToken.None);
+        }
+
+        public static Task<int?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Min(source, selector, CancellationToken.None);
+        }
+
+        public static Task<long?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Min(source, selector, CancellationToken.None);
+        }
+
+        public static Task<double?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Min(source, selector, CancellationToken.None);
+        }
+
+
+        public static Task<int> Min(this IAsyncEnumerable<int> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(Math.Min, cancellationToken);
+        }
+
+        public static Task<long> Min(this IAsyncEnumerable<long> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(Math.Min, cancellationToken);
+        }
+
+        public static Task<double> Min(this IAsyncEnumerable<double> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(Math.Min, cancellationToken);
+        }
+
+        public static Task<float> Min(this IAsyncEnumerable<float> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(Math.Min, cancellationToken);
+        }
+
+        public static Task<decimal> Min(this IAsyncEnumerable<decimal> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(Math.Min, cancellationToken);
+        }
+
+        public static Task<int?> Min(this IAsyncEnumerable<int?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(default(int?), NullableMin, cancellationToken);
+        }
+
+        public static Task<long?> Min(this IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(default(long?), NullableMin, cancellationToken);
+        }
+
+        public static Task<double?> Min(this IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(default(double?), NullableMin, cancellationToken);
+        }
+
+        public static Task<float?> Min(this IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(default(float?), NullableMin, cancellationToken);
+        }
+
+        public static Task<decimal?> Min(this IAsyncEnumerable<decimal?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(default(decimal?), NullableMin, cancellationToken);
+        }
+
+        public static Task<TSource> Min<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            var comparer = Comparer<TSource>.Default;
+            return source.Aggregate((x, y) => comparer.Compare(x, y) <= 0 ? x : y, cancellationToken);
+        }
+
+        public static Task<int> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Min(cancellationToken);
+        }
+
+        public static Task<long> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Min(cancellationToken);
+        }
+
+        public static Task<double> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Min(cancellationToken);
+        }
+
+        public static Task<float> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Min(cancellationToken);
+        }
+
+        public static Task<decimal> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Min(cancellationToken);
+        }
+
+        public static Task<int?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Min(cancellationToken);
+        }
+
+        public static Task<long?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Min(cancellationToken);
+        }
+
+        public static Task<double?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Min(cancellationToken);
+        }
+
+        public static Task<float?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Min(cancellationToken);
+        }
+
+
+        public static Task<TSource> Min<TSource>(this IAsyncEnumerable<TSource> source, IComparer<TSource> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (comparer == null)
+                throw new ArgumentNullException("comparer");
+
+            return source.Min(comparer, CancellationToken.None);
+        }
+
+        public static Task<decimal?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Min(cancellationToken);
+        }
+
+        public static Task<TResult> Min<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Min(cancellationToken);
+        }
+
+
+        public static Task<float?> Min<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Min(source, selector, CancellationToken.None);
+        }
+
+        public static Task<IList<TSource>> MinBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (keySelector == null)
+                throw new ArgumentNullException("keySelector");
+
+            return source.MinBy(keySelector, CancellationToken.None);
+        }
+
+        public static Task<IList<TSource>> MinBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (keySelector == null)
+                throw new ArgumentNullException("keySelector");
+            if (comparer == null)
+                throw new ArgumentNullException("comparer");
+
+            return source.MinBy(keySelector, comparer, CancellationToken.None);
+        }
+
+        public static Task<IList<TSource>> MinBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return MinBy(source, keySelector, Comparer<TKey>.Default, cancellationToken);
+        }
+
+        public static Task<IList<TSource>> MinBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return ExtremaBy(source, keySelector, (key, minValue) => -comparer.Compare(key, minValue), cancellationToken);
+        }
+
+
+        private static async Task<IList<TSource>> ExtremaBy<TSource, TKey>(IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, TKey, int> compare, CancellationToken cancellationToken)
+        {
+            var result = new List<TSource>();
+
+            using (var e = source.GetEnumerator())
+            {
+                if (!await e.MoveNext(cancellationToken)
+                            .ConfigureAwait(false))
+                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
+
+                var current = e.Current;
+                var resKey = keySelector(current);
+                result.Add(current);
+
+                while (await e.MoveNext(cancellationToken)
+                              .ConfigureAwait(false))
+                {
+                    var cur = e.Current;
+                    var key = keySelector(cur);
+
+                    var cmp = compare(key, resKey);
+                    if (cmp == 0)
+                    {
+                        result.Add(cur);
+                    }
+                    else if (cmp > 0)
+                    {
+                        result = new List<TSource>
+                        {
+                            cur
+                        };
+                        resKey = key;
+                    }
+                }
+            }
+
+            return result;
+        }
+
+        private static async Task<TSource> Min_<TSource>(IAsyncEnumerable<TSource> source, IComparer<TSource> comparer, CancellationToken cancellationToken)
+        {
+            return (await MinBy(source, x => x, comparer, cancellationToken)
+                        .ConfigureAwait(false)).First();
+        }
+
+        private static T? NullableMin<T>(T? x, T? y)
+            where T : struct, IComparable<T>
+        {
+            if (!x.HasValue)
+                return y;
+            if (!y.HasValue)
+                return x;
+            if (x.Value.CompareTo(y.Value) <= 0)
+                return x;
+            return y;
+        }
+    }
+}

+ 97 - 0
Ix.NET/Source/System.Interactive.Async/OnErrorResumeNext.cs

@@ -0,0 +1,97 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> OnErrorResumeNext<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            return OnErrorResumeNext_(new[] {first, second});
+        }
+
+        public static IAsyncEnumerable<TSource> OnErrorResumeNext<TSource>(params IAsyncEnumerable<TSource>[] sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return OnErrorResumeNext_(sources);
+        }
+
+        public static IAsyncEnumerable<TSource> OnErrorResumeNext<TSource>(this IEnumerable<IAsyncEnumerable<TSource>> sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return OnErrorResumeNext_(sources);
+        }
+
+        private static IAsyncEnumerable<TSource> OnErrorResumeNext_<TSource>(IEnumerable<IAsyncEnumerable<TSource>> sources)
+        {
+            return Create(() =>
+                          {
+                              var se = sources.GetEnumerator();
+                              var e = default(IAsyncEnumerator<TSource>);
+
+                              var cts = new CancellationTokenDisposable();
+                              var a = new AssignableDisposable();
+                              var d = Disposable.Create(cts, se, a);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (e == null)
+                                      {
+                                          var b = false;
+                                          b = se.MoveNext();
+                                          if (b)
+                                              e = se.Current.GetEnumerator();
+                                          else
+                                          {
+                                              return false;
+                                          }
+
+                                          a.Disposable = e;
+                                      }
+
+                                      try
+                                      {
+                                          if (await e.MoveNext(ct)
+                                                     .ConfigureAwait(false))
+                                          {
+                                              return true;
+                                          }
+                                      }
+                                      catch
+                                      {
+                                          // ignore
+                                      }
+
+                                      e.Dispose();
+                                      e = null;
+                                      return await f(ct)
+                                                 .ConfigureAwait(false);
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => e.Current,
+                                  d.Dispose,
+                                  a
+                              );
+                          });
+        }
+    }
+}

+ 218 - 0
Ix.NET/Source/System.Interactive.Async/OrderBy.cs

@@ -0,0 +1,218 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IOrderedAsyncEnumerable<TSource> OrderBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return new OrderedAsyncEnumerable<TSource, TKey>(
+                Create(() =>
+                       {
+                           var current = default(IEnumerable<TSource>);
+
+                           return Create(
+                               async ct =>
+                               {
+                                   if (current == null)
+                                   {
+                                       current = await source.ToList(ct)
+                                                             .ConfigureAwait(false);
+                                       return true;
+                                   }
+                                   return false;
+                               },
+                               () => current,
+                               () => { }
+                           );
+                       }),
+                keySelector,
+                comparer
+            );
+        }
+
+        public static IOrderedAsyncEnumerable<TSource> OrderBy<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.OrderBy(keySelector, Comparer<TKey>.Default);
+        }
+
+        public static IOrderedAsyncEnumerable<TSource> OrderByDescending<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.OrderBy(keySelector, new ReverseComparer<TKey>(comparer));
+        }
+
+        public static IOrderedAsyncEnumerable<TSource> OrderByDescending<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.OrderByDescending(keySelector, Comparer<TKey>.Default);
+        }
+
+        public static IOrderedAsyncEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.ThenBy(keySelector, Comparer<TKey>.Default);
+        }
+
+        public static IOrderedAsyncEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.CreateOrderedEnumerable(keySelector, comparer, false);
+        }
+
+        public static IOrderedAsyncEnumerable<TSource> ThenByDescending<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.ThenByDescending(keySelector, Comparer<TKey>.Default);
+        }
+
+        public static IOrderedAsyncEnumerable<TSource> ThenByDescending<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.CreateOrderedEnumerable(keySelector, comparer, true);
+        }
+
+        private class OrderedAsyncEnumerable<T, K> : IOrderedAsyncEnumerable<T>
+        {
+            private readonly IComparer<K> comparer;
+            private readonly IAsyncEnumerable<IEnumerable<T>> equivalenceClasses;
+            private readonly Func<T, K> keySelector;
+
+            public OrderedAsyncEnumerable(IAsyncEnumerable<IEnumerable<T>> equivalenceClasses, Func<T, K> keySelector, IComparer<K> comparer)
+            {
+                this.equivalenceClasses = equivalenceClasses;
+                this.keySelector = keySelector;
+                this.comparer = comparer;
+            }
+
+            public IOrderedAsyncEnumerable<T> CreateOrderedEnumerable<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer, bool descending)
+            {
+                if (descending)
+                    comparer = new ReverseComparer<TKey>(comparer);
+
+                return new OrderedAsyncEnumerable<T, TKey>(Classes(), keySelector, comparer);
+            }
+
+            public IAsyncEnumerator<T> GetEnumerator()
+            {
+                return Classes()
+                    .SelectMany(x => x.ToAsyncEnumerable())
+                    .GetEnumerator();
+            }
+
+            private IAsyncEnumerable<IEnumerable<T>> Classes()
+            {
+                return Create(() =>
+                              {
+                                  var e = equivalenceClasses.GetEnumerator();
+                                  var list = new List<IEnumerable<T>>();
+                                  var e1 = default(IEnumerator<IEnumerable<T>>);
+
+                                  var cts = new CancellationTokenDisposable();
+                                  var d1 = new AssignableDisposable();
+                                  var d = Disposable.Create(cts, e, d1);
+
+                                  var f = default(Func<CancellationToken, Task<bool>>);
+
+                                  f = async ct =>
+                                      {
+                                          if (await e.MoveNext(ct)
+                                                     .ConfigureAwait(false))
+                                          {
+                                              list.AddRange(e.Current.OrderBy(keySelector, comparer)
+                                                             .GroupUntil(keySelector, x => x, comparer));
+                                              return await f(ct)
+                                                         .ConfigureAwait(false);
+                                          }
+                                          e.Dispose();
+
+                                          e1 = list.GetEnumerator();
+                                          d1.Disposable = e1;
+
+                                          return e1.MoveNext();
+                                      };
+
+                                  return Create(
+                                      async ct =>
+                                      {
+                                          if (e1 != null)
+                                          {
+                                              return e1.MoveNext();
+                                          }
+                                          return await f(cts.Token)
+                                                     .ConfigureAwait(false);
+                                      },
+                                      () => e1.Current,
+                                      d.Dispose,
+                                      e
+                                  );
+                              });
+            }
+        }
+
+        private class ReverseComparer<T> : IComparer<T>
+        {
+            private readonly IComparer<T> comparer;
+
+            public ReverseComparer(IComparer<T> comparer)
+            {
+                this.comparer = comparer;
+            }
+
+            public int Compare(T x, T y)
+            {
+                return -comparer.Compare(x, y);
+            }
+        }
+    }
+}

+ 23 - 0
Ix.NET/Source/System.Interactive.Async/Range.cs

@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<int> Range(int start, int count)
+        {
+            if (count < 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            return Enumerable.Range(start, count)
+                             .ToAsyncEnumerable();
+        }
+    }
+}

+ 133 - 0
Ix.NET/Source/System.Interactive.Async/Repeat.cs

@@ -0,0 +1,133 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TResult> Repeat<TResult>(TResult element, int count)
+        {
+            if (count < 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            return Enumerable.Repeat(element, count)
+                             .ToAsyncEnumerable();
+        }
+
+        public static IAsyncEnumerable<TResult> Repeat<TResult>(TResult element)
+        {
+            return Create(() =>
+                          {
+                              return Create(
+                                  ct => TaskExt.True,
+                                  () => element,
+                                  () => { }
+                              );
+                          });
+        }
+
+
+        public static IAsyncEnumerable<TSource> Repeat<TSource>(this IAsyncEnumerable<TSource> source, int count)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count < 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            return Create(() =>
+                          {
+                              var e = default(IAsyncEnumerator<TSource>);
+                              var a = new AssignableDisposable();
+                              var n = count;
+                              var current = default(TSource);
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, a);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (e == null)
+                                      {
+                                          if (n-- == 0)
+                                          {
+                                              return false;
+                                          }
+
+                                          e = source.GetEnumerator();
+
+                                          a.Disposable = e;
+                                      }
+
+                                      if (await e.MoveNext(ct)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          current = e.Current;
+                                          return true;
+                                      }
+                                      e = null;
+                                      return await f(ct)
+                                                 .ConfigureAwait(false);
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TSource> Repeat<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create(() =>
+                          {
+                              var e = default(IAsyncEnumerator<TSource>);
+                              var a = new AssignableDisposable();
+                              var current = default(TSource);
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, a);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (e == null)
+                                      {
+                                          e = source.GetEnumerator();
+
+                                          a.Disposable = e;
+                                      }
+
+                                      if (await e.MoveNext(ct)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          current = e.Current;
+                                          return true;
+                                      }
+                                      e = null;
+                                      return await f(ct)
+                                                 .ConfigureAwait(false);
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 48 - 0
Ix.NET/Source/System.Interactive.Async/Retry.cs

@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Retry<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return new[] {source}.Repeat()
+                                 .Catch();
+        }
+
+        public static IAsyncEnumerable<TSource> Retry<TSource>(this IAsyncEnumerable<TSource> source, int retryCount)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (retryCount < 0)
+                throw new ArgumentOutOfRangeException(nameof(retryCount));
+
+            return new[] {source}.Repeat(retryCount)
+                                 .Catch();
+        }
+
+        private static IEnumerable<TSource> Repeat<TSource>(this IEnumerable<TSource> source)
+        {
+            while (true)
+                foreach (var item in source)
+                    yield return item;
+        }
+
+        private static IEnumerable<TSource> Repeat<TSource>(this IEnumerable<TSource> source, int count)
+        {
+            for (var i = 0; i < count; i++)
+                foreach (var item in source)
+                    yield return item;
+        }
+    }
+}

+ 51 - 0
Ix.NET/Source/System.Interactive.Async/Reverse.cs

@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Reverse<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+                              var stack = default(Stack<TSource>);
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              return Create(
+                                  async ct =>
+                                  {
+                                      if (stack == null)
+                                      {
+                                          stack = await Create(() => e)
+                                                      .Aggregate(new Stack<TSource>(), (s, x) =>
+                                                                                       {
+                                                                                           s.Push(x);
+                                                                                           return s;
+                                                                                       }, cts.Token)
+                                                      .ConfigureAwait(false);
+                                          return stack.Count > 0;
+                                      }
+                                      stack.Pop();
+                                      return stack.Count > 0;
+                                  },
+                                  () => stack.Peek(),
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 109 - 0
Ix.NET/Source/System.Interactive.Async/Scan.cs

@@ -0,0 +1,109 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TAccumulate> Scan<TSource, TAccumulate>(this IAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (accumulator == null)
+                throw new ArgumentNullException(nameof(accumulator));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var acc = seed;
+                              var current = default(TAccumulate);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (!await e.MoveNext(ct)
+                                                  .ConfigureAwait(false))
+                                      {
+                                          return false;
+                                      }
+
+                                      var item = e.Current;
+                                      acc = accumulator(acc, item);
+
+                                      current = acc;
+                                      return true;
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TSource> Scan<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (accumulator == null)
+                throw new ArgumentNullException(nameof(accumulator));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var hasSeed = false;
+                              var acc = default(TSource);
+                              var current = default(TSource);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (!await e.MoveNext(ct)
+                                                  .ConfigureAwait(false))
+                                      {
+                                          return false;
+                                      }
+
+                                      var item = e.Current;
+
+                                      if (!hasSeed)
+                                      {
+                                          hasSeed = true;
+                                          acc = item;
+                                          return await f(ct)
+                                                     .ConfigureAwait(false);
+                                      }
+
+                                      acc = accumulator(acc, item);
+
+                                      current = acc;
+                                      return true;
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 81 - 0
Ix.NET/Source/System.Interactive.Async/Select.cs

@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TResult> Select<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+                              var current = default(TResult);
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              return Create(
+                                  async ct =>
+                                  {
+                                      if (await e.MoveNext(cts.Token)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          current = selector(e.Current);
+                                          return true;
+                                      }
+                                      return false;
+                                  },
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TResult> Select<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, int, TResult> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+                              var current = default(TResult);
+                              var index = 0;
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              return Create(
+                                  async ct =>
+                                  {
+                                      if (await e.MoveNext(cts.Token)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          current = selector(e.Current, checked(index++));
+                                          return true;
+                                      }
+                                      return false;
+                                  },
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 164 - 0
Ix.NET/Source/System.Interactive.Async/SelectMany.cs

@@ -0,0 +1,164 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TOther> SelectMany<TSource, TOther>(this IAsyncEnumerable<TSource> source, IAsyncEnumerable<TOther> other)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (other == null)
+                throw new ArgumentNullException(nameof(other));
+
+            return source.SelectMany(_ => other);
+        }
+
+
+        public static IAsyncEnumerable<TResult> SelectMany<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, IAsyncEnumerable<TResult>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+                              var ie = default(IAsyncEnumerator<TResult>);
+
+                              var innerDisposable = new AssignableDisposable();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, innerDisposable, e);
+
+                              var inner = default(Func<CancellationToken, Task<bool>>);
+                              var outer = default(Func<CancellationToken, Task<bool>>);
+
+                              inner = async ct =>
+                                      {
+                                          if (await ie.MoveNext(ct)
+                                                      .ConfigureAwait(false))
+                                          {
+                                              return true;
+                                          }
+                                          innerDisposable.Disposable = null;
+                                          return await outer(ct)
+                                                     .ConfigureAwait(false);
+                                      };
+
+                              outer = async ct =>
+                                      {
+                                          if (await e.MoveNext(ct)
+                                                     .ConfigureAwait(false))
+                                          {
+                                              var enumerable = selector(e.Current);
+                                              ie = enumerable.GetEnumerator();
+                                              innerDisposable.Disposable = ie;
+
+                                              return await inner(ct)
+                                                         .ConfigureAwait(false);
+                                          }
+                                          return false;
+                                      };
+
+                              return Create(ct => ie == null ? outer(cts.Token) : inner(cts.Token),
+                                            () => ie.Current,
+                                            d.Dispose,
+                                            e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TResult> SelectMany<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, int, IAsyncEnumerable<TResult>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+                              var ie = default(IAsyncEnumerator<TResult>);
+
+                              var index = 0;
+
+                              var innerDisposable = new AssignableDisposable();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, innerDisposable, e);
+
+                              var inner = default(Func<CancellationToken, Task<bool>>);
+                              var outer = default(Func<CancellationToken, Task<bool>>);
+
+                              inner = async ct =>
+                                      {
+                                          if (await ie.MoveNext(ct)
+                                                      .ConfigureAwait(false))
+                                          {
+                                              return true;
+                                          }
+                                          innerDisposable.Disposable = null;
+                                          return await outer(ct)
+                                                     .ConfigureAwait(false);
+                                      };
+
+                              outer = async ct =>
+                                      {
+                                          if (await e.MoveNext(ct)
+                                                     .ConfigureAwait(false))
+                                          {
+                                              var enumerable = selector(e.Current, checked(index++));
+                                              ie = enumerable.GetEnumerator();
+                                              innerDisposable.Disposable = ie;
+
+                                              return await inner(ct)
+                                                         .ConfigureAwait(false);
+                                          }
+                                          return false;
+                                      };
+
+                              return Create(ct => ie == null ? outer(cts.Token) : inner(cts.Token),
+                                            () => ie.Current,
+                                            d.Dispose,
+                                            e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, IAsyncEnumerable<TCollection>> selector, Func<TSource, TCollection, TResult> resultSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+
+            return source.SelectMany(x => selector(x)
+                                         .Select(y => resultSelector(x, y)));
+        }
+
+        public static IAsyncEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, int, IAsyncEnumerable<TCollection>> selector, Func<TSource, TCollection, TResult> resultSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+
+            return source.SelectMany((x, i) => selector(x, i)
+                                         .Select(y => resultSelector(x, y)));
+        }
+    }
+}

+ 81 - 0
Ix.NET/Source/System.Interactive.Async/SequenceEqual.cs

@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<bool> SequenceEqual<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
+        {
+            if (first == null)
+                throw new ArgumentNullException("first");
+            if (second == null)
+                throw new ArgumentNullException("second");
+            if (comparer == null)
+                throw new ArgumentNullException("comparer");
+
+            return SequenceEqual(first, second, comparer, CancellationToken.None);
+        }
+
+        public static Task<bool> SequenceEqual<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
+        {
+            if (first == null)
+                throw new ArgumentNullException("first");
+            if (second == null)
+                throw new ArgumentNullException("second");
+
+            return SequenceEqual(first, second, CancellationToken.None);
+        }
+
+
+        public static Task<bool> SequenceEqual<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return SequenceEqual_(first, second, comparer, cancellationToken);
+        }
+
+        public static Task<bool> SequenceEqual<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, CancellationToken cancellationToken)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            return first.SequenceEqual(second, EqualityComparer<TSource>.Default, cancellationToken);
+        }
+
+        private static async Task<bool> SequenceEqual_<TSource>(IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer,
+                                                                CancellationToken cancellationToken)
+        {
+            using (var e1 = first.GetEnumerator())
+            using (var e2 = second.GetEnumerator())
+            {
+                while (await e1.MoveNext(cancellationToken)
+                               .ConfigureAwait(false))
+                {
+                    if (!(await e2.MoveNext(cancellationToken)
+                                  .ConfigureAwait(false) && comparer.Equals(e1.Current, e2.Current)))
+                    {
+                        return false;
+                    }
+                }
+
+                return !await e2.MoveNext(cancellationToken)
+                                .ConfigureAwait(false);
+            }
+        }
+    }
+}

+ 11 - 0
Ix.NET/Source/System.Interactive.Async/Set.cs

@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+    }
+}

+ 129 - 0
Ix.NET/Source/System.Interactive.Async/Single.cs

@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<TSource> Single<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Single(source, CancellationToken.None);
+        }
+
+        public static Task<TSource> Single<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (predicate == null)
+                throw new ArgumentNullException("predicate");
+
+            return Single(source, predicate, CancellationToken.None);
+        }
+
+
+        public static Task<TSource> Single<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Single_(source, cancellationToken);
+        }
+
+        public static Task<TSource> Single<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return source.Where(predicate)
+                         .Single(cancellationToken);
+        }
+
+        public static Task<TSource> SingleOrDefault<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return SingleOrDefault(source, CancellationToken.None);
+        }
+
+        public static Task<TSource> SingleOrDefault<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (predicate == null)
+                throw new ArgumentNullException("predicate");
+
+            return SingleOrDefault(source, predicate, CancellationToken.None);
+        }
+
+        public static Task<TSource> SingleOrDefault<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return SingleOrDefault_(source, cancellationToken);
+        }
+
+        public static Task<TSource> SingleOrDefault<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return source.Where(predicate)
+                         .SingleOrDefault(cancellationToken);
+        }
+
+        private static async Task<TSource> Single_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                if (!await e.MoveNext(cancellationToken)
+                            .ConfigureAwait(false))
+                {
+                    throw new InvalidOperationException(Strings.NO_ELEMENTS);
+                }
+                var result = e.Current;
+                if (await e.MoveNext(cancellationToken)
+                           .ConfigureAwait(false))
+                {
+                    throw new InvalidOperationException(Strings.MORE_THAN_ONE_ELEMENT);
+                }
+                return result;
+            }
+        }
+
+        private static async Task<TSource> SingleOrDefault_<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                if (!await e.MoveNext(cancellationToken)
+                            .ConfigureAwait(false))
+                {
+                    return default(TSource);
+                }
+
+                var result = e.Current;
+                if (!await e.MoveNext(cancellationToken)
+                            .ConfigureAwait(false))
+                {
+                    return result;
+                }
+            }
+            throw new InvalidOperationException(Strings.MORE_THAN_ONE_ELEMENT);
+        }
+    }
+}

+ 192 - 0
Ix.NET/Source/System.Interactive.Async/Skip.cs

@@ -0,0 +1,192 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Skip<TSource>(this IAsyncEnumerable<TSource> source, int count)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count < 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+                              var n = count;
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      var moveNext = await e.MoveNext(ct)
+                                                            .ConfigureAwait(false);
+                                      if (n == 0)
+                                      {
+                                          return moveNext;
+                                      }
+                                      --n;
+                                      if (!moveNext)
+                                      {
+                                          return false;
+                                      }
+                                      return await f(ct)
+                                                 .ConfigureAwait(false);
+                                  };
+
+                              return Create(
+                                  ct => f(cts.Token),
+                                  () => e.Current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TSource> SkipLast<TSource>(this IAsyncEnumerable<TSource> source, int count)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count < 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var q = new Queue<TSource>();
+                              var current = default(TSource);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (await e.MoveNext(ct)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          var item = e.Current;
+
+                                          q.Enqueue(item);
+                                          if (q.Count > count)
+                                          {
+                                              current = q.Dequeue();
+                                              return true;
+                                          }
+                                          return await f(ct)
+                                                     .ConfigureAwait(false);
+                                      }
+                                      return false;
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+                              var skipping = true;
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (skipping)
+                                      {
+                                          if (await e.MoveNext(ct)
+                                                     .ConfigureAwait(false))
+                                          {
+                                              if (predicate(e.Current))
+                                                  return await f(ct)
+                                                             .ConfigureAwait(false);
+                                              skipping = false;
+                                              return true;
+                                          }
+                                          return false;
+                                      }
+                                      return await e.MoveNext(ct)
+                                                    .ConfigureAwait(false);
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => e.Current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+                              var skipping = true;
+                              var index = 0;
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (skipping)
+                                      {
+                                          if (await e.MoveNext(ct)
+                                                     .ConfigureAwait(false))
+                                          {
+                                              if (predicate(e.Current, checked(index++)))
+                                                  return await f(ct)
+                                                             .ConfigureAwait(false);
+                                              skipping = false;
+                                              return true;
+                                          }
+                                          return false;
+                                      }
+                                      return await e.MoveNext(ct)
+                                                    .ConfigureAwait(false);
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => e.Current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 23 - 0
Ix.NET/Source/System.Interactive.Async/StartsWith.cs

@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> StartWith<TSource>(this IAsyncEnumerable<TSource> source, params TSource[] values)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return values.ToAsyncEnumerable()
+                         .Concat(source);
+        }
+    }
+}

+ 387 - 0
Ix.NET/Source/System.Interactive.Async/Sum.cs

@@ -0,0 +1,387 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<int> Sum(this IAsyncEnumerable<int> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(0, (x, y) => x + y, cancellationToken);
+        }
+
+        public static Task<long> Sum(this IAsyncEnumerable<long> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(0L, (x, y) => x + y, cancellationToken);
+        }
+
+        public static Task<double> Sum(this IAsyncEnumerable<double> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(0.0, (x, y) => x + y, cancellationToken);
+        }
+
+        public static Task<float> Sum(this IAsyncEnumerable<float> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(0f, (x, y) => x + y, cancellationToken);
+        }
+
+        public static Task<decimal> Sum(this IAsyncEnumerable<decimal> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(0m, (x, y) => x + y, cancellationToken);
+        }
+
+        public static Task<int?> Sum(this IAsyncEnumerable<int?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate((int?)0, (x, y) => x + y.GetValueOrDefault(), cancellationToken);
+        }
+
+        public static Task<long?> Sum(this IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate((long?)0, (x, y) => x + y.GetValueOrDefault(), cancellationToken);
+        }
+
+        public static Task<double?> Sum(this IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate((double?)0, (x, y) => x + y.GetValueOrDefault(), cancellationToken);
+        }
+
+        public static Task<float?> Sum(this IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate((float?)0, (x, y) => x + y.GetValueOrDefault(), cancellationToken);
+        }
+
+        public static Task<decimal?> Sum(this IAsyncEnumerable<decimal?> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate((decimal?)0, (x, y) => x + y.GetValueOrDefault(), cancellationToken);
+        }
+
+        public static Task<int> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Sum(cancellationToken);
+        }
+
+        public static Task<long> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Sum(cancellationToken);
+        }
+
+        public static Task<double> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Sum(cancellationToken);
+        }
+
+        public static Task<float> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Sum(cancellationToken);
+        }
+
+        public static Task<decimal> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Sum(cancellationToken);
+        }
+
+        public static Task<int?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Sum(cancellationToken);
+        }
+
+        public static Task<long?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Sum(cancellationToken);
+        }
+
+        public static Task<double?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Sum(cancellationToken);
+        }
+
+
+        public static Task<int> Sum(this IAsyncEnumerable<int> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Sum(source, CancellationToken.None);
+        }
+
+        public static Task<long> Sum(this IAsyncEnumerable<long> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Sum(source, CancellationToken.None);
+        }
+
+        public static Task<double> Sum(this IAsyncEnumerable<double> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Sum(source, CancellationToken.None);
+        }
+
+        public static Task<float> Sum(this IAsyncEnumerable<float> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Sum(source, CancellationToken.None);
+        }
+
+        public static Task<decimal> Sum(this IAsyncEnumerable<decimal> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Sum(source, CancellationToken.None);
+        }
+
+        public static Task<int?> Sum(this IAsyncEnumerable<int?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Sum(source, CancellationToken.None);
+        }
+
+        public static Task<long?> Sum(this IAsyncEnumerable<long?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Sum(source, CancellationToken.None);
+        }
+
+        public static Task<double?> Sum(this IAsyncEnumerable<double?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Sum(source, CancellationToken.None);
+        }
+
+        public static Task<float?> Sum(this IAsyncEnumerable<float?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Sum(source, CancellationToken.None);
+        }
+
+        public static Task<decimal?> Sum(this IAsyncEnumerable<decimal?> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return Sum(source, CancellationToken.None);
+        }
+
+        public static Task<int> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Sum(source, selector, CancellationToken.None);
+        }
+
+        public static Task<long> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Sum(source, selector, CancellationToken.None);
+        }
+
+        public static Task<double> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Sum(source, selector, CancellationToken.None);
+        }
+
+        public static Task<float> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Sum(source, selector, CancellationToken.None);
+        }
+
+        public static Task<decimal> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Sum(source, selector, CancellationToken.None);
+        }
+
+        public static Task<int?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Sum(source, selector, CancellationToken.None);
+        }
+
+        public static Task<long?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Sum(source, selector, CancellationToken.None);
+        }
+
+        public static Task<double?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Sum(source, selector, CancellationToken.None);
+        }
+
+        public static Task<float?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Sum(source, selector, CancellationToken.None);
+        }
+
+        public static Task<decimal?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (selector == null)
+                throw new ArgumentNullException("selector");
+
+            return Sum(source, selector, CancellationToken.None);
+        }
+
+
+        public static Task<float?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Sum(cancellationToken);
+        }
+
+        public static Task<decimal?> Sum<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Select(selector)
+                         .Sum(cancellationToken);
+        }
+    }
+}

+ 176 - 0
Ix.NET/Source/System.Interactive.Async/Take.cs

@@ -0,0 +1,176 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Take<TSource>(this IAsyncEnumerable<TSource> source, int count)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count < 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+                              var n = count;
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              return Create(
+                                  async ct =>
+                                  {
+                                      if (n == 0)
+                                          return false;
+
+                                      var result = await e.MoveNext(cts.Token)
+                                                          .ConfigureAwait(false);
+
+                                      --n;
+
+                                      if (n == 0)
+                                          e.Dispose();
+
+                                      return result;
+                                  },
+                                  () => e.Current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TSource> TakeLast<TSource>(this IAsyncEnumerable<TSource> source, int count)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count < 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var q = new Queue<TSource>(count);
+                              var done = false;
+                              var current = default(TSource);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (!done)
+                                      {
+                                          if (await e.MoveNext(ct)
+                                                     .ConfigureAwait(false))
+                                          {
+                                              if (count > 0)
+                                              {
+                                                  var item = e.Current;
+                                                  if (q.Count >= count)
+                                                      q.Dequeue();
+                                                  q.Enqueue(item);
+                                              }
+                                          }
+                                          else
+                                          {
+                                              done = true;
+                                              e.Dispose();
+                                          }
+
+                                          return await f(ct)
+                                                     .ConfigureAwait(false);
+                                      }
+                                      if (q.Count > 0)
+                                      {
+                                          current = q.Dequeue();
+                                          return true;
+                                      }
+                                      return false;
+                                  };
+
+                              return Create(
+                                  f,
+                                  () => current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TSource> TakeWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              return Create(
+                                  async ct =>
+                                  {
+                                      if (await e.MoveNext(cts.Token)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          return predicate(e.Current);
+                                      }
+                                      return false;
+                                  },
+                                  () => e.Current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TSource> TakeWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+                              var index = 0;
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              return Create(
+                                  async ct =>
+                                  {
+                                      if (await e.MoveNext(cts.Token)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          return predicate(e.Current, checked(index++));
+                                      }
+                                      return false;
+                                  },
+                                  () => e.Current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 92 - 0
Ix.NET/Source/System.Interactive.Async/ToAsyncEnumerable.cs

@@ -0,0 +1,92 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using System.Threading;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> ToAsyncEnumerable<TSource>(this IEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create(() =>
+            {
+                var e = source.GetEnumerator();
+
+                return Create(
+                    ct => Task.Run(() =>
+                    {
+                        var res = false;
+                        try
+                        {
+                            res = e.MoveNext();
+                        }
+                        finally
+                        {
+                            if (!res)
+                                e.Dispose();
+                        }
+                        return res;
+                    }, ct),
+                    () => e.Current,
+                    () => e.Dispose()
+                );
+            });
+        }
+
+        public static IEnumerable<TSource> ToEnumerable<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return ToEnumerable_(source);
+        }
+
+        private static IEnumerable<TSource> ToEnumerable_<TSource>(IAsyncEnumerable<TSource> source)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                while (true)
+                {
+                    if (!e.MoveNext(CancellationToken.None).Result)
+                        break;
+                    var c = e.Current;
+                    yield return c;
+                }
+            }
+        }
+
+        public static IAsyncEnumerable<TSource> ToAsyncEnumerable<TSource>(this Task<TSource> task)
+        {
+            if (task == null)
+                throw new ArgumentNullException(nameof(task));
+            
+            return Create(() =>
+            {
+                var called = 0;
+
+                var value = default(TSource);
+                return Create(
+                    async ct =>
+                    {
+                        if (Interlocked.CompareExchange(ref called, 1, 0) == 0)
+                        {
+                            value = await task.ConfigureAwait(false);
+                            return true;
+                        }
+                        return false;
+                    },
+                    () => value,
+                    () => { });
+            });
+        }
+
+
+    }
+}

+ 155 - 0
Ix.NET/Source/System.Interactive.Async/ToCollection.cs

@@ -0,0 +1,155 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static Task<TSource[]> ToArray<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return ToArray(source, CancellationToken.None);
+        }
+
+        public static Task<TSource[]> ToArray<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(new List<TSource>(), (list, x) =>
+                                                         {
+                                                             list.Add(x);
+                                                             return list;
+                                                         }, list => list.ToArray(), cancellationToken);
+        }
+
+        public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (keySelector == null)
+                throw new ArgumentNullException("keySelector");
+            if (elementSelector == null)
+                throw new ArgumentNullException("elementSelector");
+            if (comparer == null)
+                throw new ArgumentNullException("comparer");
+
+            return ToDictionary(source, keySelector, elementSelector, comparer, CancellationToken.None);
+        }
+
+        public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (keySelector == null)
+                throw new ArgumentNullException("keySelector");
+            if (elementSelector == null)
+                throw new ArgumentNullException("elementSelector");
+
+            return ToDictionary(source, keySelector, elementSelector, CancellationToken.None);
+        }
+
+        public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (keySelector == null)
+                throw new ArgumentNullException("keySelector");
+            if (comparer == null)
+                throw new ArgumentNullException("comparer");
+
+            return ToDictionary(source, keySelector, comparer, CancellationToken.None);
+        }
+
+        public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (keySelector == null)
+                throw new ArgumentNullException("keySelector");
+
+            return ToDictionary(source, keySelector, CancellationToken.None);
+        }
+
+        public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (elementSelector == null)
+                throw new ArgumentNullException(nameof(elementSelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.Aggregate(new Dictionary<TKey, TElement>(comparer), (d, x) =>
+                                                                              {
+                                                                                  d.Add(keySelector(x), elementSelector(x));
+                                                                                  return d;
+                                                                              }, cancellationToken);
+        }
+
+        public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (elementSelector == null)
+                throw new ArgumentNullException(nameof(elementSelector));
+
+            return source.ToDictionary(keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
+        }
+
+        public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.ToDictionary(keySelector, x => x, comparer, cancellationToken);
+        }
+
+        public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.ToDictionary(keySelector, x => x, EqualityComparer<TKey>.Default, cancellationToken);
+        }
+
+        public static Task<List<TSource>> ToList<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            return ToList(source, CancellationToken.None);
+        }
+
+        public static Task<List<TSource>> ToList<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Aggregate(new List<TSource>(), (list, x) =>
+                                                         {
+                                                             list.Add(x);
+                                                             return list;
+                                                         }, cancellationToken);
+        }
+    }
+}

+ 220 - 0
Ix.NET/Source/System.Interactive.Async/ToObservable.cs

@@ -0,0 +1,220 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> ToAsyncEnumerable<TSource>(this IObservable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Create(() =>
+                          {
+                              var observer = new ToAsyncEnumerableObserver<TSource>();
+
+                              var subscription = source.Subscribe(observer);
+
+                              return Create(
+                                  (ct, tcs) =>
+                                  {
+                                      var hasValue = false;
+                                      var hasCompleted = false;
+                                      var error = default(Exception);
+
+                                      lock (observer.SyncRoot)
+                                      {
+                                          if (observer.Values.Count > 0)
+                                          {
+                                              hasValue = true;
+                                              observer.Current = observer.Values.Dequeue();
+                                          }
+                                          else if (observer.HasCompleted)
+                                          {
+                                              hasCompleted = true;
+                                          }
+                                          else if (observer.Error != null)
+                                          {
+                                              error = observer.Error;
+                                          }
+                                          else
+                                          {
+                                              observer.TaskCompletionSource = tcs;
+                                          }
+                                      }
+
+                                      if (hasValue)
+                                      {
+                                          tcs.TrySetResult(true);
+                                      }
+                                      else if (hasCompleted)
+                                      {
+                                          tcs.TrySetResult(false);
+                                      }
+                                      else if (error != null)
+                                      {
+                                          tcs.TrySetException(error);
+                                      }
+
+                                      return tcs.Task;
+                                  },
+                                  () => observer.Current,
+                                  () =>
+                                  {
+                                      subscription.Dispose();
+                                      // Should we cancel in-flight operations somehow?
+                                  });
+                          });
+        }
+
+        public static IObservable<TSource> ToObservable<TSource>(this IAsyncEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return new ToObservableObservable<TSource>(source);
+        }
+
+        private class ToAsyncEnumerableObserver<T> : IObserver<T>
+        {
+            public readonly Queue<T> Values;
+
+            public T Current;
+            public Exception Error;
+            public bool HasCompleted;
+            public TaskCompletionSource<bool> TaskCompletionSource;
+
+            public ToAsyncEnumerableObserver()
+            {
+                Values = new Queue<T>();
+            }
+
+            public object SyncRoot
+            {
+                get { return Values; }
+            }
+
+            public void OnCompleted()
+            {
+                var tcs = default(TaskCompletionSource<bool>);
+
+                lock (SyncRoot)
+                {
+                    HasCompleted = true;
+
+                    if (TaskCompletionSource != null)
+                    {
+                        tcs = TaskCompletionSource;
+                        TaskCompletionSource = null;
+                    }
+                }
+
+                if (tcs != null)
+                {
+                    tcs.SetResult(false);
+                }
+            }
+
+            public void OnError(Exception error)
+            {
+                var tcs = default(TaskCompletionSource<bool>);
+
+                lock (SyncRoot)
+                {
+                    Error = error;
+
+                    if (TaskCompletionSource != null)
+                    {
+                        tcs = TaskCompletionSource;
+                        TaskCompletionSource = null;
+                    }
+                }
+
+                if (tcs != null)
+                {
+                    tcs.SetException(error);
+                }
+            }
+
+            public void OnNext(T value)
+            {
+                var tcs = default(TaskCompletionSource<bool>);
+
+                lock (SyncRoot)
+                {
+                    if (TaskCompletionSource == null)
+                    {
+                        Values.Enqueue(value);
+                    }
+                    else
+                    {
+                        Current = value;
+
+                        tcs = TaskCompletionSource;
+                        TaskCompletionSource = null;
+                    }
+                }
+
+                if (tcs != null)
+                {
+                    tcs.SetResult(true);
+                }
+            }
+        }
+
+        private class ToObservableObservable<T> : IObservable<T>
+        {
+            private readonly IAsyncEnumerable<T> source;
+
+            public ToObservableObservable(IAsyncEnumerable<T> source)
+            {
+                this.source = source;
+            }
+
+            public IDisposable Subscribe(IObserver<T> observer)
+            {
+                var ctd = new CancellationTokenDisposable();
+                var e = source.GetEnumerator();
+
+                var f = default(Action);
+                f = () => e.MoveNext(ctd.Token)
+                           .ContinueWith(t =>
+                                         {
+                                             if (t.IsFaulted)
+                                             {
+                                                 observer.OnError(t.Exception);
+                                                 e.Dispose();
+                                             }
+                                             else if (t.IsCanceled)
+                                             {
+                                                 e.Dispose();
+                                             }
+                                             else if (t.IsCompleted)
+                                             {
+                                                 if (t.Result)
+                                                 {
+                                                     observer.OnNext(e.Current);
+                                                     f();
+                                                 }
+                                                 else
+                                                 {
+                                                     observer.OnCompleted();
+                                                     e.Dispose();
+                                                 }
+                                             }
+                                         }, ctd.Token);
+
+                f();
+
+                return Disposable.Create(ctd, e);
+            }
+        }
+    }
+}

+ 37 - 0
Ix.NET/Source/System.Interactive.Async/Union.cs

@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Union<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return first.Concat(second)
+                        .Distinct(comparer);
+        }
+
+        public static IAsyncEnumerable<TSource> Union<TSource>(this IAsyncEnumerable<TSource> first, IAsyncEnumerable<TSource> second)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            return first.Union(second, EqualityComparer<TSource>.Default);
+        }
+    }
+}

+ 71 - 0
Ix.NET/Source/System.Interactive.Async/Using.cs

@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Using<TSource, TResource>(Func<TResource> resourceFactory, Func<TResource, IAsyncEnumerable<TSource>> enumerableFactory) where TResource : IDisposable
+        {
+            if (resourceFactory == null)
+                throw new ArgumentNullException(nameof(resourceFactory));
+            if (enumerableFactory == null)
+                throw new ArgumentNullException(nameof(enumerableFactory));
+
+            return Create(() =>
+                          {
+                              var resource = resourceFactory();
+                              var e = default(IAsyncEnumerator<TSource>);
+
+                              try
+                              {
+                                  e = enumerableFactory(resource)
+                                      .GetEnumerator();
+                              }
+                              catch (Exception)
+                              {
+                                  resource.Dispose();
+                                  throw;
+                              }
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, resource, e);
+
+                              var current = default(TSource);
+
+                              return Create(
+                                  async ct =>
+                                  {
+                                      bool res;
+                                      try
+                                      {
+                                          res = await e.MoveNext(cts.Token)
+                                                       .ConfigureAwait(false);
+                                      }
+                                      catch (Exception)
+                                      {
+                                          d.Dispose();
+                                          throw;
+                                      }
+                                      if (res)
+                                      {
+                                          current = e.Current;
+                                          return true;
+                                      }
+                                      d.Dispose();
+                                      return false;
+                                  },
+                                  () => current,
+                                  d.Dispose,
+                                  null
+                              );
+                          });
+        }
+    }
+}

+ 90 - 0
Ix.NET/Source/System.Interactive.Async/Where.cs

@@ -0,0 +1,90 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TSource> Where<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (await e.MoveNext(ct)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          if (predicate(e.Current))
+                                              return true;
+                                          return await f(ct)
+                                                     .ConfigureAwait(false);
+                                      }
+                                      return false;
+                                  };
+
+                              return Create(
+                                  ct => f(cts.Token),
+                                  () => e.Current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+
+        public static IAsyncEnumerable<TSource> Where<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (predicate == null)
+                throw new ArgumentNullException(nameof(predicate));
+
+            return Create(() =>
+                          {
+                              var e = source.GetEnumerator();
+                              var index = 0;
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e);
+
+                              var f = default(Func<CancellationToken, Task<bool>>);
+                              f = async ct =>
+                                  {
+                                      if (await e.MoveNext(ct)
+                                                 .ConfigureAwait(false))
+                                      {
+                                          if (predicate(e.Current, checked(index++)))
+                                              return true;
+                                          return await f(ct)
+                                                     .ConfigureAwait(false);
+                                      }
+                                      return false;
+                                  };
+
+                              return Create(
+                                  ct => f(cts.Token),
+                                  () => e.Current,
+                                  d.Dispose,
+                                  e
+                              );
+                          });
+        }
+    }
+}

+ 47 - 0
Ix.NET/Source/System.Interactive.Async/Zip.cs

@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerable
+    {
+        public static IAsyncEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IAsyncEnumerable<TFirst> first, IAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> selector)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create(() =>
+                          {
+                              var e1 = first.GetEnumerator();
+                              var e2 = second.GetEnumerator();
+                              var current = default(TResult);
+
+                              var cts = new CancellationTokenDisposable();
+                              var d = Disposable.Create(cts, e1, e2);
+
+                              return Create(
+                                  ct => e1.MoveNext(cts.Token)
+                                          .Zip(e2.MoveNext(cts.Token), (f, s) =>
+                                                                       {
+                                                                           var result = f && s;
+                                                                           if (result)
+                                                                               current = selector(e1.Current, e2.Current);
+                                                                           return result;
+                                                                       }),
+                                  () => current,
+                                  d.Dispose
+                              );
+                          });
+        }
+    }
+}

+ 83 - 0
Ix.NET/Source/System.Interactive/Buffer.cs

@@ -0,0 +1,83 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Generates a sequence of non-overlapping adjacent buffers over the source sequence.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="count">Number of elements for allocated buffers.</param>
+        /// <returns>Sequence of buffers containing source sequence elements.</returns>
+        public static IEnumerable<IList<TSource>> Buffer<TSource>(this IEnumerable<TSource> source, int count)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count <= 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            return source.Buffer_(count, count);
+        }
+
+        /// <summary>
+        ///     Generates a sequence of buffers over the source sequence, with specified length and possible overlap.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="count">Number of elements for allocated buffers.</param>
+        /// <param name="skip">Number of elements to skip between the start of consecutive buffers.</param>
+        /// <returns>Sequence of buffers containing source sequence elements.</returns>
+        public static IEnumerable<IList<TSource>> Buffer<TSource>(this IEnumerable<TSource> source, int count, int skip)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count <= 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+            if (skip <= 0)
+                throw new ArgumentOutOfRangeException(nameof(skip));
+
+            return source.Buffer_(count, skip);
+        }
+
+        private static IEnumerable<IList<TSource>> Buffer_<TSource>(this IEnumerable<TSource> source, int count, int skip)
+        {
+            var buffers = new Queue<IList<TSource>>();
+
+            var i = 0;
+            foreach (var item in source)
+            {
+                if (i%skip == 0)
+                    buffers.Enqueue(new List<TSource>(count));
+
+                foreach (var buffer in buffers)
+                    buffer.Add(item);
+
+                if (buffers.Count > 0 && buffers.Peek()
+                                                .Count == count)
+                    yield return buffers.Dequeue();
+
+                i++;
+            }
+
+            while (buffers.Count > 0)
+                yield return buffers.Dequeue();
+        }
+    }
+
+    /// <summary>
+    ///     Represents a buffer exposing a shared view over an underlying enumerable sequence.
+    /// </summary>
+    /// <typeparam name="T">Element type.</typeparam>
+    public interface IBuffer<out T> : IEnumerable<T>, IDisposable
+    {
+    }
+}

+ 63 - 0
Ix.NET/Source/System.Interactive/Case.cs

@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Returns a sequence from a dictionary based on the result of evaluating a selector function.
+        /// </summary>
+        /// <typeparam name="TValue">Type of the selector value.</typeparam>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="selector">Selector function used to pick a sequence from the given sources.</param>
+        /// <param name="sources">Dictionary mapping selector values onto resulting sequences.</param>
+        /// <returns>The source sequence corresponding with the evaluated selector value; otherwise, an empty sequence.</returns>
+        public static IEnumerable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IEnumerable<TResult>> sources)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return Case(selector, sources, Enumerable.Empty<TResult>());
+        }
+
+        /// <summary>
+        ///     Returns a sequence from a dictionary based on the result of evaluating a selector function, also specifying a
+        ///     default sequence.
+        /// </summary>
+        /// <typeparam name="TValue">Type of the selector value.</typeparam>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="selector">Selector function used to pick a sequence from the given sources.</param>
+        /// <param name="sources">Dictionary mapping selector values onto resulting sequences.</param>
+        /// <param name="defaultSource">
+        ///     Default sequence to return in case there's no corresponding source for the computed
+        ///     selector value.
+        /// </param>
+        /// <returns>The source sequence corresponding with the evaluated selector value; otherwise, the default source.</returns>
+        public static IEnumerable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IEnumerable<TResult>> sources, IEnumerable<TResult> defaultSource)
+        {
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+            if (defaultSource == null)
+                throw new ArgumentNullException(nameof(defaultSource));
+
+            return Defer(() =>
+                         {
+                             IEnumerable<TResult> result;
+                             if (!sources.TryGetValue(selector(), out result))
+                                 result = defaultSource;
+                             return result;
+                         });
+        }
+    }
+}

+ 153 - 0
Ix.NET/Source/System.Interactive/Catch.cs

@@ -0,0 +1,153 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Creates a sequence that corresponds to the source sequence, concatenating it with the sequence resulting from
+        ///     calling an exception handler function in case of an error.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TException">Exception type to catch.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="handler">Handler to invoke when an exception of the specified type occurs.</param>
+        /// <returns>Source sequence, concatenated with an exception handler result sequence in case of an error.</returns>
+        public static IEnumerable<TSource> Catch<TSource, TException>(this IEnumerable<TSource> source, Func<TException, IEnumerable<TSource>> handler)
+            where TException : Exception
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (handler == null)
+                throw new ArgumentNullException(nameof(handler));
+
+            return source.Catch_(handler);
+        }
+
+        /// <summary>
+        ///     Creates a sequence by concatenating source sequences until a source sequence completes successfully.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="sources">Source sequences.</param>
+        /// <returns>Sequence that continues to concatenate source sequences while errors occur.</returns>
+        public static IEnumerable<TSource> Catch<TSource>(this IEnumerable<IEnumerable<TSource>> sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return sources.Catch_();
+        }
+
+        /// <summary>
+        ///     Creates a sequence by concatenating source sequences until a source sequence completes successfully.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="sources">Source sequences.</param>
+        /// <returns>Sequence that continues to concatenate source sequences while errors occur.</returns>
+        public static IEnumerable<TSource> Catch<TSource>(params IEnumerable<TSource>[] sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return sources.Catch_();
+        }
+
+        /// <summary>
+        ///     Creates a sequence that returns the elements of the first sequence, switching to the second in case of an error.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="first">First sequence.</param>
+        /// <param name="second">Second sequence, concatenated to the result in case the first sequence completes exceptionally.</param>
+        /// <returns>The first sequence, followed by the second sequence in case an error is produced.</returns>
+        public static IEnumerable<TSource> Catch<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            return new[] {first, second}.Catch_();
+        }
+
+        private static IEnumerable<TSource> Catch_<TSource, TException>(this IEnumerable<TSource> source, Func<TException, IEnumerable<TSource>> handler)
+            where TException : Exception
+        {
+            var err = default(IEnumerable<TSource>);
+
+            using (var e = source.GetEnumerator())
+            {
+                while (true)
+                {
+                    var c = default(TSource);
+
+                    try
+                    {
+                        if (!e.MoveNext())
+                            break;
+
+                        c = e.Current;
+                    }
+                    catch (TException ex)
+                    {
+                        err = handler(ex);
+                        break;
+                    }
+
+                    yield return c;
+                }
+            }
+
+            if (err != null)
+            {
+                foreach (var item in err)
+                    yield return item;
+            }
+        }
+
+        private static IEnumerable<TSource> Catch_<TSource>(this IEnumerable<IEnumerable<TSource>> sources)
+        {
+            var error = default(Exception);
+
+            foreach (var source in sources)
+            {
+                using (var e = source.GetEnumerator())
+                {
+                    error = null;
+
+                    while (true)
+                    {
+                        var c = default(TSource);
+
+                        try
+                        {
+                            if (!e.MoveNext())
+                                break;
+
+                            c = e.Current;
+                        }
+                        catch (Exception ex)
+                        {
+                            error = ex;
+                            break;
+                        }
+
+                        yield return c;
+                    }
+
+                    if (error == null)
+                        break;
+                }
+            }
+
+            if (error != null)
+                throw error;
+        }
+    }
+}

+ 49 - 0
Ix.NET/Source/System.Interactive/Concatenate.cs

@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Concatenates the input sequences.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="sources">Source sequences.</param>
+        /// <returns>Sequence with the elements of the source sequences concatenated.</returns>
+        public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<IEnumerable<TSource>> sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return sources.Concat_();
+        }
+
+        /// <summary>
+        ///     Concatenates the input sequences.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="sources">Source sequences.</param>
+        /// <returns>Sequence with the elements of the source sequences concatenated.</returns>
+        public static IEnumerable<TSource> Concat<TSource>(params IEnumerable<TSource>[] sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return sources.Concat_();
+        }
+
+        private static IEnumerable<TSource> Concat_<TSource>(this IEnumerable<IEnumerable<TSource>> sources)
+        {
+            foreach (var source in sources)
+                foreach (var item in source)
+                    yield return item;
+        }
+    }
+}

+ 67 - 0
Ix.NET/Source/System.Interactive/Create.cs

@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Creates an enumerable sequence based on an enumerator factory function.
+        /// </summary>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="getEnumerator">Enumerator factory function.</param>
+        /// <returns>Sequence that will invoke the enumerator factory upon a call to GetEnumerator.</returns>
+        public static IEnumerable<TResult> Create<TResult>(Func<IEnumerator<TResult>> getEnumerator)
+        {
+            if (getEnumerator == null)
+                throw new ArgumentNullException(nameof(getEnumerator));
+
+            return new AnonymousEnumerable<TResult>(getEnumerator);
+        }
+
+        /// <summary>
+        ///     Creates an enumerable sequence based on an asynchronous method that provides a yielder.
+        /// </summary>
+        /// <typeparam name="T">Result sequence element type.</typeparam>
+        /// <param name="create">
+        ///     Delegate implementing an asynchronous method that can use the specified yielder to yield return
+        ///     values.
+        /// </param>
+        /// <returns>Sequence that will use the asynchronous method to obtain its elements.</returns>
+        public static IEnumerable<T> Create<T>(Action<IYielder<T>> create)
+        {
+            if (create == null)
+                throw new ArgumentNullException(nameof(create));
+
+            foreach (var x in new Yielder<T>(create))
+                yield return x;
+        }
+
+        private class AnonymousEnumerable<TResult> : IEnumerable<TResult>
+        {
+            private readonly Func<IEnumerator<TResult>> _getEnumerator;
+
+            public AnonymousEnumerable(Func<IEnumerator<TResult>> getEnumerator)
+            {
+                _getEnumerator = getEnumerator;
+            }
+
+            public IEnumerator<TResult> GetEnumerator()
+            {
+                return _getEnumerator();
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                return GetEnumerator();
+            }
+        }
+    }
+}

+ 34 - 0
Ix.NET/Source/System.Interactive/Defer.cs

@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Creates an enumerable sequence based on an enumerable factory function.
+        /// </summary>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="enumerableFactory">Enumerable factory function.</param>
+        /// <returns>Sequence that will invoke the enumerable factory upon a call to GetEnumerator.</returns>
+        public static IEnumerable<TResult> Defer<TResult>(Func<IEnumerable<TResult>> enumerableFactory)
+        {
+            if (enumerableFactory == null)
+                throw new ArgumentNullException(nameof(enumerableFactory));
+
+            return Defer_(enumerableFactory);
+        }
+
+        private static IEnumerable<TSource> Defer_<TSource>(Func<IEnumerable<TSource>> enumerableFactory)
+        {
+            foreach (var item in enumerableFactory())
+                yield return item;
+        }
+    }
+}

+ 157 - 0
Ix.NET/Source/System.Interactive/Distinct.cs

@@ -0,0 +1,157 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+
+        /// <summary>
+        /// Returns elements with a distinct key value by using the default equality comparer to compare key values.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TKey">Key type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="keySelector">Key selector.</param>
+        /// <returns>Sequence that contains the elements from the source sequence with distinct key values.</returns>
+        public static IEnumerable<TSource> Distinct<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.Distinct_(keySelector, EqualityComparer<TKey>.Default);
+        }
+
+        /// <summary>
+        /// Returns elements with a distinct key value by using the specified equality comparer to compare key values.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TKey">Key type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="keySelector">Key selector.</param>
+        /// <param name="comparer">Comparer used to compare key values.</param>
+        /// <returns>Sequence that contains the elements from the source sequence with distinct key values.</returns>
+        public static IEnumerable<TSource> Distinct<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.Distinct_(keySelector, comparer);
+        }
+
+        private static IEnumerable<TSource> Distinct_<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            var set = new HashSet<TKey>(comparer);
+
+            foreach (var item in source)
+            {
+                var key = keySelector(item);
+                if (set.Add(key))
+                    yield return item;
+            }
+        }
+
+        /// <summary>
+        /// Returns consecutive distinct elements by using the default equality comparer to compare values.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <returns>Sequence without adjacent non-distinct elements.</returns>
+        public static IEnumerable<TSource> DistinctUntilChanged<TSource>(this IEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.DistinctUntilChanged_(x => x, EqualityComparer<TSource>.Default);
+        }
+
+        /// <summary>
+        /// Returns consecutive distinct elements by using the specified equality comparer to compare values.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="comparer">Comparer used to compare values.</param>
+        /// <returns>Sequence without adjacent non-distinct elements.</returns>
+        public static IEnumerable<TSource> DistinctUntilChanged<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.DistinctUntilChanged_(x => x, comparer);
+        }
+
+        /// <summary>
+        /// Returns consecutive distinct elements based on a key value by using the specified equality comparer to compare key values.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TKey">Key type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="keySelector">Key selector.</param>
+        /// <returns>Sequence without adjacent non-distinct elements.</returns>
+        public static IEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return source.DistinctUntilChanged_(keySelector, EqualityComparer<TKey>.Default);
+        }
+
+        /// <summary>
+        /// Returns consecutive distinct elements based on a key value by using the specified equality comparer to compare key values.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TKey">Key type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="keySelector">Key selector.</param>
+        /// <param name="comparer">Comparer used to compare key values.</param>
+        /// <returns>Sequence without adjacent non-distinct elements.</returns>
+        public static IEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return source.DistinctUntilChanged_(keySelector, comparer);
+        }
+
+        private static IEnumerable<TSource> DistinctUntilChanged_<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+        {
+            var currentKey = default(TKey);
+            var hasCurrentKey = false;
+
+            foreach (var item in source)
+            {
+                var key = keySelector(item);
+
+                var comparerEquals = false;
+                if (hasCurrentKey)
+                {
+                    comparerEquals = comparer.Equals(currentKey, key);
+                }
+
+                if (!hasCurrentKey || !comparerEquals)
+                {
+                    hasCurrentKey = true;
+                    currentKey = key;
+                    yield return item;
+                }
+            }
+        }
+
+    }
+}

+ 157 - 0
Ix.NET/Source/System.Interactive/Do.cs

@@ -0,0 +1,157 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Lazily invokes an action for each value in the sequence.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="onNext">Action to invoke for each element.</param>
+        /// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
+        public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            return DoHelper(source, onNext, _ => { }, () => { });
+        }
+
+        /// <summary>
+        ///     Lazily invokes an action for each value in the sequence, and executes an action for successful termination.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="onNext">Action to invoke for each element.</param>
+        /// <param name="onCompleted">Action to invoke on successful termination of the sequence.</param>
+        /// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
+        public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return DoHelper(source, onNext, _ => { }, onCompleted);
+        }
+
+        /// <summary>
+        ///     Lazily invokes an action for each value in the sequence, and executes an action upon exceptional termination.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="onNext">Action to invoke for each element.</param>
+        /// <param name="onError">Action to invoke on exceptional termination of the sequence.</param>
+        /// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
+        public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+
+            return DoHelper(source, onNext, onError, () => { });
+        }
+
+        /// <summary>
+        ///     Lazily invokes an action for each value in the sequence, and executes an action upon successful or exceptional
+        ///     termination.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="onNext">Action to invoke for each element.</param>
+        /// <param name="onError">Action to invoke on exceptional termination of the sequence.</param>
+        /// <param name="onCompleted">Action to invoke on successful termination of the sequence.</param>
+        /// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
+        public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+            if (onError == null)
+                throw new ArgumentNullException(nameof(onError));
+            if (onCompleted == null)
+                throw new ArgumentNullException(nameof(onCompleted));
+
+            return DoHelper(source, onNext, onError, onCompleted);
+        }
+
+        /// <summary>
+        ///     Lazily invokes observer methods for each value in the sequence, and upon successful or exceptional termination.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="observer">Observer to invoke notification calls on.</param>
+        /// <returns>Sequence exhibiting the side-effects of observer method invocation upon enumeration.</returns>
+        public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, IObserver<TSource> observer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (observer == null)
+                throw new ArgumentNullException(nameof(observer));
+
+            return DoHelper(source, observer.OnNext, observer.OnError, observer.OnCompleted);
+        }
+
+        /// <summary>
+        ///     Generates an enumerable sequence by repeating a source sequence as long as the given loop postcondition holds.
+        /// </summary>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="source">Source sequence to repeat while the condition evaluates true.</param>
+        /// <param name="condition">Loop condition.</param>
+        /// <returns>Sequence generated by repeating the given sequence until the condition evaluates to false.</returns>
+        public static IEnumerable<TResult> DoWhile<TResult>(this IEnumerable<TResult> source, Func<bool> condition)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (condition == null)
+                throw new ArgumentNullException(nameof(condition));
+
+            return source.Concat(While(condition, source));
+        }
+
+        private static IEnumerable<TSource> DoHelper<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
+        {
+            using (var e = source.GetEnumerator())
+            {
+                while (true)
+                {
+                    var current = default(TSource);
+                    try
+                    {
+                        if (!e.MoveNext())
+                            break;
+
+                        current = e.Current;
+                    }
+                    catch (Exception ex)
+                    {
+                        onError(ex);
+                        throw;
+                    }
+
+                    onNext(current);
+                    yield return current;
+                }
+
+                onCompleted();
+            }
+        }
+    }
+}

+ 28 - 0
Ix.NET/Source/System.Interactive/Empty.cs

@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Determines whether an enumerable sequence is empty.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <returns>true if the sequence is empty; false otherwise.</returns>
+        public static bool IsEmpty<TSource>(this IEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return !source.Any();
+        }
+    }
+}

+ 0 - 175
Ix.NET/Source/System.Interactive/EnumerableEx.Aggregates.cs

@@ -1,175 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace System.Linq
-{
-    /// <summary>
-    /// Provides a set of additional static methods that allow querying enumerable sequences.
-    /// </summary>
-    public static partial class EnumerableEx
-    {
-        /// <summary>
-        /// Determines whether an enumerable sequence is empty.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <returns>true if the sequence is empty; false otherwise.</returns>
-        public static bool IsEmpty<TSource>(this IEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return !source.Any();
-        }
-
-        /// <summary>
-        /// Returns the minimum value in the enumerable sequence by using the specified comparer to compare values.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="comparer">Comparer used to determine the minimum value.</param>
-        /// <returns>Minimum value in the sequence.</returns>
-        public static TSource Min<TSource>(this IEnumerable<TSource> source, IComparer<TSource> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return MinBy(source, x => x, comparer).First();
-        }
-
-        /// <summary>
-        /// Returns the elements with the minimum key value by using the default comparer to compare key values.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TKey">Key type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="keySelector">Key selector used to extract the key for each element in the sequence.</param>
-        /// <returns>List with the elements that share the same minimum key value.</returns>
-        public static IList<TSource> MinBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return MinBy(source, keySelector, Comparer<TKey>.Default);
-        }
-
-        /// <summary>
-        /// Returns the elements with the minimum key value by using the specified comparer to compare key values.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TKey">Key type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="keySelector">Key selector used to extract the key for each element in the sequence.</param>
-        /// <param name="comparer">Comparer used to determine the minimum key value.</param>
-        /// <returns>List with the elements that share the same minimum key value.</returns>
-        public static IList<TSource> MinBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return ExtremaBy(source, keySelector, (key, minValue) => -comparer.Compare(key, minValue));
-        }
-
-        /// <summary>
-        /// Returns the maximum value in the enumerable sequence by using the specified comparer to compare values.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="comparer">Comparer used to determine the maximum value.</param>
-        /// <returns>Maximum value in the sequence.</returns>
-        public static TSource Max<TSource>(this IEnumerable<TSource> source, IComparer<TSource> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return MaxBy(source, x => x, comparer).First();
-        }
-
-        /// <summary>
-        /// Returns the elements with the maximum key value by using the default comparer to compare key values.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TKey">Key type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="keySelector">Key selector used to extract the key for each element in the sequence.</param>
-        /// <returns>List with the elements that share the same maximum key value.</returns>
-        public static IList<TSource> MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return MaxBy(source, keySelector, Comparer<TKey>.Default);
-        }
-
-        /// <summary>
-        /// Returns the elements with the minimum key value by using the specified comparer to compare key values.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TKey">Key type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="keySelector">Key selector used to extract the key for each element in the sequence.</param>
-        /// <param name="comparer">Comparer used to determine the maximum key value.</param>
-        /// <returns>List with the elements that share the same maximum key value.</returns>
-        public static IList<TSource> MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return ExtremaBy(source, keySelector, (key, minValue) => comparer.Compare(key, minValue));
-        }
-
-        private static IList<TSource> ExtremaBy<TSource, TKey>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, TKey, int> compare)
-        {
-            var result = new List<TSource>();
-
-            using (var e = source.GetEnumerator())
-            {
-                if (!e.MoveNext())
-                    throw new InvalidOperationException("Source sequence doesn't contain any elements.");
-
-                var current = e.Current;
-                var resKey = keySelector(current);
-                result.Add(current);
-
-                while (e.MoveNext())
-                {
-                    var cur = e.Current;
-                    var key = keySelector(cur);
-
-                    var cmp = compare(key, resKey);
-                    if (cmp == 0)
-                    {
-                        result.Add(cur);
-                    }
-                    else if (cmp > 0)
-                    {
-                        result = new List<TSource> { cur };
-                        resKey = key;
-                    }
-                }
-            }
-
-            return result;
-        }
-    }
-}

+ 0 - 649
Ix.NET/Source/System.Interactive/EnumerableEx.Buffering.cs

@@ -1,649 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-
-namespace System.Linq
-{
-    public static partial class EnumerableEx
-    {
-        /// <summary>
-        /// Creates a buffer with a shared view over the source sequence, causing each enumerator to fetch the next element from the source sequence.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <returns>Buffer enabling each enumerator to retrieve elements from the shared source sequence.</returns>
-        /// <example>
-        /// var rng = Enumerable.Range(0, 10).Share();
-        /// 
-        /// var e1 = rng.GetEnumerator();    // Both e1 and e2 will consume elements from
-        /// var e2 = rng.GetEnumerator();    // the source sequence.
-        /// 
-        /// Assert.IsTrue(e1.MoveNext());
-        /// Assert.AreEqual(0, e1.Current);
-        /// 
-        /// Assert.IsTrue(e1.MoveNext());
-        /// Assert.AreEqual(1, e1.Current);
-        /// 
-        /// Assert.IsTrue(e2.MoveNext());    // e2 "steals" element 2
-        /// Assert.AreEqual(2, e2.Current);
-        /// 
-        /// Assert.IsTrue(e1.MoveNext());    // e1 can't see element 2
-        /// Assert.AreEqual(3, e1.Current);
-        /// </example>
-        public static IBuffer<TSource> Share<TSource>(this IEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return new SharedBuffer<TSource>(source.GetEnumerator());
-        }
-
-        /// <summary>
-        /// Shares the source sequence within a selector function where each enumerator can fetch the next element from the source sequence.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="selector">Selector function with shared access to the source sequence for each enumerator.</param>
-        /// <returns>Sequence resulting from applying the selector function to the shared view over the source sequence.</returns>
-        public static IEnumerable<TResult> Share<TSource, TResult>(this IEnumerable<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return Create<TResult>(() => selector(source.Share()).GetEnumerator());
-        }
-
-        class SharedBuffer<T> : IBuffer<T>
-        {
-            private IEnumerator<T> _source;
-            private bool _disposed;
-
-            public SharedBuffer(IEnumerator<T> source)
-            {
-                _source = source;
-            }
-
-            public IEnumerator<T> GetEnumerator()
-            {
-                if (_disposed)
-                    throw new ObjectDisposedException("");
-
-                return GetEnumerator_();
-            }
-
-            private IEnumerator<T> GetEnumerator_()
-            {
-                while (true)
-                {
-                    if (_disposed)
-                        throw new ObjectDisposedException("");
-
-                    var hasValue = default(bool);
-                    var current = default(T);
-
-                    lock (_source)
-                    {
-                        hasValue = _source.MoveNext();
-                        if (hasValue)
-                            current = _source.Current;
-                    }
-
-                    if (hasValue)
-                        yield return current;
-                    else
-                        break;
-                }
-            }
-
-            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
-            {
-                if (_disposed)
-                    throw new ObjectDisposedException("");
-
-                return GetEnumerator();
-            }
-
-            public void Dispose()
-            {
-                lock (_source)
-                {
-                    if (!_disposed)
-                    {
-                        _source.Dispose();
-                        _source = null;
-                    }
-
-                    _disposed = true;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Creates a buffer with a view over the source sequence, causing each enumerator to obtain access to the remainder of the sequence from the current index in the buffer.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <returns>Buffer enabling each enumerator to retrieve elements from the shared source sequence, starting from the index at the point of obtaining the enumerator.</returns>
-        /// <example>
-        /// var rng = Enumerable.Range(0, 10).Publish();
-        /// 
-        /// var e1 = rng.GetEnumerator();    // e1 has a view on the source starting from element 0
-        /// 
-        /// Assert.IsTrue(e1.MoveNext());
-        /// Assert.AreEqual(0, e1.Current);
-        /// 
-        /// Assert.IsTrue(e1.MoveNext());
-        /// Assert.AreEqual(1, e1.Current);
-        /// 
-        /// var e2 = rng.GetEnumerator();
-        /// 
-        /// Assert.IsTrue(e2.MoveNext());    // e2 has a view on the source starting from element 2
-        /// Assert.AreEqual(2, e2.Current);
-        /// 
-        /// Assert.IsTrue(e1.MoveNext());    // e1 continues to enumerate over its view
-        /// Assert.AreEqual(2, e1.Current);
-        /// </example>
-        public static IBuffer<TSource> Publish<TSource>(this IEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return new PublishedBuffer<TSource>(source.GetEnumerator());
-        }
-
-        /// <summary>
-        /// Publishes the source sequence within a selector function where each enumerator can obtain a view over a tail of the source sequence.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="selector">Selector function with published access to the source sequence for each enumerator.</param>
-        /// <returns>Sequence resulting from applying the selector function to the published view over the source sequence.</returns>
-        public static IEnumerable<TResult> Publish<TSource, TResult>(this IEnumerable<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return Create<TResult>(() => selector(source.Publish()).GetEnumerator());
-        }
-
-        class PublishedBuffer<T> : IBuffer<T>
-        {
-            private IEnumerator<T> _source;
-            private RefCountList<T> _buffer;
-            private bool _stopped;
-            private Exception _error;
-            private bool _disposed;
-
-            public PublishedBuffer(IEnumerator<T> source)
-            {
-                _buffer = new RefCountList<T>(0);
-                _source = source;
-            }
-
-            public IEnumerator<T> GetEnumerator()
-            {
-                if (_disposed)
-                    throw new ObjectDisposedException("");
-
-                var i = default(int);
-                lock (_source)
-                {
-                    i = _buffer.Count;
-                    _buffer.ReaderCount++;
-                } 
-                
-                return GetEnumerator_(i);
-            }
-
-            private IEnumerator<T> GetEnumerator_(int i)
-            {
-                try
-                {
-                    while (true)
-                    {
-                        if (_disposed)
-                            throw new ObjectDisposedException("");
-
-                        var hasValue = default(bool);
-                        var current = default(T);
-
-                        lock (_source)
-                        {
-                            if (i >= _buffer.Count)
-                            {
-                                if (!_stopped)
-                                {
-                                    try
-                                    {
-                                        hasValue = _source.MoveNext();
-                                        if (hasValue)
-                                            current = _source.Current;
-                                    }
-                                    catch (Exception ex)
-                                    {
-                                        _stopped = true;
-                                        _error = ex;
-
-                                        _source.Dispose();
-                                    }
-                                }
-
-                                if (_stopped)
-                                {
-                                    if (_error != null)
-                                        throw _error;
-                                    else
-                                        break;
-                                }
-
-                                if (hasValue)
-                                {
-                                    _buffer.Add(current);
-                                }
-                            }
-                            else
-                            {
-                                hasValue = true;
-                            }
-                        }
-
-                        if (hasValue)
-                            yield return _buffer[i];
-                        else
-                            break;
-
-                        i++;
-                    }
-                }
-                finally
-                {
-                    if (_buffer != null)
-                        _buffer.Done(i + 1);
-                }
-            }
-
-            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
-            {
-                if (_disposed)
-                    throw new ObjectDisposedException("");
-
-                return GetEnumerator();
-            }
-
-            public void Dispose()
-            {
-                lock (_source)
-                {
-                    if (!_disposed)
-                    {
-                        _source.Dispose();
-                        _source = null;
-
-                        _buffer.Clear();
-                        _buffer = null;
-                    }
-
-                    _disposed = true;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Creates a buffer with a view over the source sequence, causing each enumerator to obtain access to all of the sequence's elements without causing multiple enumerations over the source.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <returns>Buffer enabling each enumerator to retrieve all elements from the shared source sequence, without duplicating source enumeration side-effects.</returns>
-        /// <example>
-        /// var rng = Enumerable.Range(0, 10).Do(x => Console.WriteLine(x)).Memoize();
-        /// 
-        /// var e1 = rng.GetEnumerator();
-        /// 
-        /// Assert.IsTrue(e1.MoveNext());    // Prints 0
-        /// Assert.AreEqual(0, e1.Current);
-        /// 
-        /// Assert.IsTrue(e1.MoveNext());    // Prints 1
-        /// Assert.AreEqual(1, e1.Current);
-        /// 
-        /// var e2 = rng.GetEnumerator();
-        /// 
-        /// Assert.IsTrue(e2.MoveNext());    // Doesn't print anything; the side-effect of Do
-        /// Assert.AreEqual(0, e2.Current);  // has already taken place during e1's iteration.
-        /// 
-        /// Assert.IsTrue(e1.MoveNext());    // Prints 2
-        /// Assert.AreEqual(2, e1.Current);
-        /// </example>
-        public static IBuffer<TSource> Memoize<TSource>(this IEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return new MemoizedBuffer<TSource>(source.GetEnumerator());
-        }
-
-        /// <summary>
-        /// Memoizes the source sequence within a selector function where each enumerator can get access to all of the sequence's elements without causing multiple enumerations over the source.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="selector">Selector function with memoized access to the source sequence for each enumerator.</param>
-        /// <returns>Sequence resulting from applying the selector function to the memoized view over the source sequence.</returns>
-        public static IEnumerable<TResult> Memoize<TSource, TResult>(this IEnumerable<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return Create<TResult>(() => selector(source.Memoize()).GetEnumerator());
-        }
-
-        /// <summary>
-        /// Creates a buffer with a view over the source sequence, causing a specified number of enumerators to obtain access to all of the sequence's elements without causing multiple enumerations over the source.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="readerCount">Number of enumerators that can access the underlying buffer. Once every enumerator has obtained an element from the buffer, the element is removed from the buffer.</param>
-        /// <returns>Buffer enabling a specified number of enumerators to retrieve all elements from the shared source sequence, without duplicating source enumeration side-effects.</returns>
-        public static IBuffer<TSource> Memoize<TSource>(this IEnumerable<TSource> source, int readerCount)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (readerCount <= 0)
-                throw new ArgumentOutOfRangeException(nameof(readerCount));
-
-            return new MemoizedBuffer<TSource>(source.GetEnumerator(), readerCount);
-        }
-
-        /// <summary>
-        /// Memoizes the source sequence within a selector function where a specified number of enumerators can get access to all of the sequence's elements without causing multiple enumerations over the source.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="readerCount">Number of enumerators that can access the underlying buffer. Once every enumerator has obtained an element from the buffer, the element is removed from the buffer.</param>
-        /// <param name="selector">Selector function with memoized access to the source sequence for a specified number of enumerators.</param>
-        /// <returns>Sequence resulting from applying the selector function to the memoized view over the source sequence.</returns>
-        public static IEnumerable<TResult> Memoize<TSource, TResult>(this IEnumerable<TSource> source, int readerCount, Func<IEnumerable<TSource>, IEnumerable<TResult>> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (readerCount <= 0)
-                throw new ArgumentOutOfRangeException(nameof(readerCount));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return Create<TResult>(() => selector(source.Memoize(readerCount)).GetEnumerator());
-        }
-
-        class MemoizedBuffer<T> : IBuffer<T>
-        {
-            private IEnumerator<T> _source;
-            private IRefCountList<T> _buffer;
-            private bool _stopped;
-            private Exception _error;
-            private bool _disposed;
-
-            public MemoizedBuffer(IEnumerator<T> source)
-                : this(source, new MaxRefCountList<T>())
-            {
-            }
-
-            public MemoizedBuffer(IEnumerator<T> source, int readerCount)
-                : this(source, new RefCountList<T>(readerCount))
-            {
-            }
-
-            private MemoizedBuffer(IEnumerator<T> source, IRefCountList<T> buffer)
-            {
-                _source = source;
-                _buffer = buffer;
-            }
-
-            public IEnumerator<T> GetEnumerator()
-            {
-                if (_disposed)
-                    throw new ObjectDisposedException("");
-
-                return GetEnumerator_();
-            }
-
-            private IEnumerator<T> GetEnumerator_()
-            {
-                var i = 0;
-
-                try
-                {
-                    while (true)
-                    {
-                        if (_disposed)
-                            throw new ObjectDisposedException("");
-
-                        var hasValue = default(bool);
-                        var current = default(T);
-
-                        lock (_source)
-                        {
-                            if (i >= _buffer.Count)
-                            {
-                                if (!_stopped)
-                                {
-                                    try
-                                    {
-                                        hasValue = _source.MoveNext();
-                                        if (hasValue)
-                                            current = _source.Current;
-                                    }
-                                    catch (Exception ex)
-                                    {
-                                        _stopped = true;
-                                        _error = ex;
-
-                                        _source.Dispose();
-                                    }
-                                }
-
-                                if (_stopped)
-                                {
-                                    if (_error != null)
-                                        throw _error;
-                                    else
-                                        break;
-                                }
-
-                                if (hasValue)
-                                {
-                                    _buffer.Add(current);
-                                }
-                            }
-                            else
-                            {
-                                hasValue = true;
-                            }
-                        }
-
-                        if (hasValue)
-                            yield return _buffer[i];
-                        else
-                            break;
-
-                        i++;
-                    }
-                }
-                finally
-                {
-                    if (_buffer != null)
-                        _buffer.Done(i + 1);
-                }
-            }
-
-            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
-            {
-                if (_disposed)
-                    throw new ObjectDisposedException("");
-
-                return GetEnumerator();
-            }
-
-            public void Dispose()
-            {
-                lock (_source)
-                {
-                    if (!_disposed)
-                    {
-                        _source.Dispose();
-                        _source = null;
-
-                        _buffer.Clear();
-                        _buffer = null;
-                    }
-
-                    _disposed = true;
-                }
-            }
-        }
-    }
-
-    /// <summary>
-    /// Represents a buffer exposing a shared view over an underlying enumerable sequence.
-    /// </summary>
-    /// <typeparam name="T">Element type.</typeparam>
-    public interface IBuffer<
-#if !NO_VARIANCE && !SILVERLIGHT4 // SL4 has defined IEnumerable with invariant T
-        out
-#endif
-        T> : IEnumerable<T>, IDisposable
-    {
-    }
-
-    interface IRefCountList<T>
-    {
-        void Clear();
-
-        int Count { get; }
-
-        T this[int i]
-        {
-            get;
-        }
-
-        void Add(T item);
-
-        void Done(int index);
-    }
-
-    class MaxRefCountList<T> : IRefCountList<T>
-    {
-        private IList<T> _list = new List<T>();
-
-        public void Clear()
-        {
-            _list.Clear();
-        }
-
-        public int Count
-        {
-            get { return _list.Count; }
-        }
-
-        public T this[int i]
-        {
-            get { return _list[i]; }
-        }
-
-        public void Add(T item)
-        {
-            _list.Add(item);
-        }
-
-        public void Done(int index)
-        {
-        }
-    }
-
-    class RefCountList<T> : IRefCountList<T>
-    {
-        private int _readerCount;
-        private readonly IDictionary<int, RefCount> _list;
-        private int _count;
-
-        public RefCountList(int readerCount)
-        {
-            _readerCount = readerCount;
-            _list = new Dictionary<int, RefCount>();
-        }
-
-        public int ReaderCount
-        {
-            get
-            {
-                return _readerCount;
-            }
-
-            set
-            {
-                _readerCount = value;
-            }
-        }
-
-        public void Clear()
-        {
-            _list.Clear();
-        }
-
-        public int Count
-        {
-            get { return _count; }
-        }
-
-        public T this[int i]
-        {
-            get
-            {
-                Debug.Assert(i < _count);
-
-                var res = default(RefCount);
-                if (!_list.TryGetValue(i, out res))
-                    throw new InvalidOperationException("Element no longer available in the buffer.");
-
-                var val = res.Value;
-                if (--res.Count == 0)
-                    _list.Remove(i);
-
-                return val;
-            }
-        }
-
-        public void Add(T item)
-        {
-            _list[_count] = new RefCount { Value = item, Count = _readerCount };
-            _count++;
-        }
-
-        public void Done(int index)
-        {
-            for (int i = index; i < _count; i++)
-            {
-                var ignore = this[i];
-            }
-
-            _readerCount--;
-        }
-
-        class RefCount
-        {
-            public int Count;
-            public T Value;
-        }
-    }
-}

+ 0 - 192
Ix.NET/Source/System.Interactive/EnumerableEx.Creation.cs

@@ -1,192 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-
-namespace System.Linq
-{
-    public static partial class EnumerableEx
-    {
-        /// <summary>
-        /// Creates an enumerable sequence based on an enumerator factory function.
-        /// </summary>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="getEnumerator">Enumerator factory function.</param>
-        /// <returns>Sequence that will invoke the enumerator factory upon a call to GetEnumerator.</returns>
-        public static IEnumerable<TResult> Create<TResult>(Func<IEnumerator<TResult>> getEnumerator)
-        {
-            if (getEnumerator == null)
-                throw new ArgumentNullException(nameof(getEnumerator));
-
-            return new AnonymousEnumerable<TResult>(getEnumerator);
-        }
-
-#if HAS_AWAIT
-        /// <summary>
-        /// Creates an enumerable sequence based on an asynchronous method that provides a yielder.
-        /// </summary>
-        /// <typeparam name="T">Result sequence element type.</typeparam>
-        /// <param name="create">Delegate implementing an asynchronous method that can use the specified yielder to yield return values.</param>
-        /// <returns>Sequence that will use the asynchronous method to obtain its elements.</returns>
-        public static IEnumerable<T> Create<T>(Action<IYielder<T>> create)
-        {
-            if (create == null)
-                throw new ArgumentNullException(nameof(create));
-
-            foreach (var x in new Yielder<T>(create))
-                yield return x;
-        }
-#endif
-
-        class AnonymousEnumerable<TResult> : IEnumerable<TResult>
-        {
-            private readonly Func<IEnumerator<TResult>> _getEnumerator;
-
-            public AnonymousEnumerable(Func<IEnumerator<TResult>> getEnumerator)
-            {
-                _getEnumerator = getEnumerator;
-            }
-
-            public IEnumerator<TResult> GetEnumerator()
-            {
-                return _getEnumerator();
-            }
-
-            Collections.IEnumerator Collections.IEnumerable.GetEnumerator()
-            {
-                return GetEnumerator();
-            }
-        }
-
-        /// <summary>
-        /// Returns a sequence with a single element.
-        /// </summary>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="value">Single element of the resulting sequence.</param>
-        /// <returns>Sequence with a single element.</returns>
-        public static IEnumerable<TResult> Return<TResult>(TResult value)
-        {
-            yield return value;
-        }
-
-        /// <summary>
-        /// Returns a sequence that throws an exception upon enumeration.
-        /// </summary>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="exception">Exception to throw upon enumerating the resulting sequence.</param>
-        /// <returns>Sequence that throws the specified exception upon enumeration.</returns>
-        public static IEnumerable<TResult> Throw<TResult>(Exception exception)
-        {
-            if (exception == null)
-                throw new ArgumentNullException(nameof(exception));
-
-            return Throw_<TResult>(exception);
-        }
-
-        private static IEnumerable<TResult> Throw_<TResult>(Exception exception)
-        {
-            throw exception;
-#pragma warning disable 0162
-            yield break;
-#pragma warning restore 0162
-        }
-
-        /// <summary>
-        /// Creates an enumerable sequence based on an enumerable factory function.
-        /// </summary>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="enumerableFactory">Enumerable factory function.</param>
-        /// <returns>Sequence that will invoke the enumerable factory upon a call to GetEnumerator.</returns>
-        public static IEnumerable<TResult> Defer<TResult>(Func<IEnumerable<TResult>> enumerableFactory)
-        {
-            if (enumerableFactory == null)
-                throw new ArgumentNullException(nameof(enumerableFactory));
-
-            return Defer_(enumerableFactory);
-        }
-
-        private static IEnumerable<TSource> Defer_<TSource>(Func<IEnumerable<TSource>> enumerableFactory)
-        {
-            foreach (var item in enumerableFactory())
-                yield return item;
-        }
-
-        /// <summary>
-        /// Generates a sequence by mimicking a for loop.
-        /// </summary>
-        /// <typeparam name="TState">State type.</typeparam>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="initialState">Initial state of the generator loop.</param>
-        /// <param name="condition">Loop condition.</param>
-        /// <param name="iterate">State update function to run after every iteration of the generator loop.</param>
-        /// <param name="resultSelector">Result selector to compute resulting sequence elements.</param>
-        /// <returns>Sequence obtained by running the generator loop, yielding computed elements.</returns>
-        public static IEnumerable<TResult> Generate<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector)
-        {
-            if (condition == null)
-                throw new ArgumentNullException(nameof(condition));
-            if (iterate == null)
-                throw new ArgumentNullException(nameof(iterate));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-
-            return Generate_(initialState, condition, iterate, resultSelector);
-        }
-
-        private static IEnumerable<TResult> Generate_<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector)
-        {
-            for (var i = initialState; condition(i); i = iterate(i))
-                yield return resultSelector(i);
-        }
-
-        /// <summary>
-        /// Generates a sequence that's dependent on a resource object whose lifetime is determined by the sequence usage duration.
-        /// </summary>
-        /// <typeparam name="TSource">Source element type.</typeparam>
-        /// <typeparam name="TResource">Resource type.</typeparam>
-        /// <param name="resourceFactory">Resource factory function.</param>
-        /// <param name="enumerableFactory">Enumerable factory function, having access to the obtained resource.</param>
-        /// <returns>Sequence whose use controls the lifetime of the associated obtained resource.</returns>
-        public static IEnumerable<TSource> Using<TSource, TResource>(Func<TResource> resourceFactory, Func<TResource, IEnumerable<TSource>> enumerableFactory) where TResource : IDisposable
-        {
-            if (resourceFactory == null)
-                throw new ArgumentNullException(nameof(resourceFactory));
-            if (enumerableFactory == null)
-                throw new ArgumentNullException(nameof(enumerableFactory));
-
-            return Using_(resourceFactory, enumerableFactory);
-        }
-
-        private static IEnumerable<TSource> Using_<TSource, TResource>(Func<TResource> resourceFactory, Func<TResource, IEnumerable<TSource>> enumerableFactory) where TResource : IDisposable
-        {
-            using (var res = resourceFactory())
-                foreach (var item in enumerableFactory(res))
-                    yield return item;
-        }
-
-        /// <summary>
-        /// Generates a sequence by repeating the given value infinitely.
-        /// </summary>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="value">Value to repreat in the resulting sequence.</param>
-        /// <returns>Sequence repeating the given value infinitely.</returns>
-        public static IEnumerable<TResult> Repeat<TResult>(TResult value)
-        {
-            while (true)
-                yield return value;
-        }
-
-        /// <summary>
-        /// Generates a sequence that contains one repeated value.
-        /// </summary>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="element">The value to be repeated.</param>
-        /// <param name="count">The number of times to repeat the value in the generated sequence.</param>
-        /// <returns>Sequence that contains a repeated value.</returns>
-        public static IEnumerable<TResult> Repeat<TResult>(TResult element, int count)
-        {
-            return Enumerable.Repeat<TResult>(element, count);
-        }
-    }
-}

+ 0 - 282
Ix.NET/Source/System.Interactive/EnumerableEx.Exceptions.cs

@@ -1,282 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace System.Linq
-{
-    public static partial class EnumerableEx
-    {
-        /// <summary>
-        /// Creates a sequence that corresponds to the source sequence, concatenating it with the sequence resulting from calling an exception handler function in case of an error.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TException">Exception type to catch.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="handler">Handler to invoke when an exception of the specified type occurs.</param>
-        /// <returns>Source sequence, concatenated with an exception handler result sequence in case of an error.</returns>
-        public static IEnumerable<TSource> Catch<TSource, TException>(this IEnumerable<TSource> source, Func<TException, IEnumerable<TSource>> handler)
-            where TException : Exception
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (handler == null)
-                throw new ArgumentNullException(nameof(handler));
-
-            return source.Catch_(handler);
-        }
-
-        private static IEnumerable<TSource> Catch_<TSource, TException>(this IEnumerable<TSource> source, Func<TException, IEnumerable<TSource>> handler)
-            where TException : Exception
-        {
-            var err = default(IEnumerable<TSource>);
-
-            using (var e = source.GetEnumerator())
-            {
-                while (true)
-                {
-                    var c = default(TSource);
-
-                    try
-                    {
-                        if (!e.MoveNext())
-                            break;
-
-                        c = e.Current;
-                    }
-                    catch (TException ex)
-                    {
-                        err = handler(ex);
-                        break;
-                    }
-
-                    yield return c;
-                }
-            }
-
-            if (err != null)
-            {
-                foreach (var item in err)
-                    yield return item;
-            }
-        }
-
-        /// <summary>
-        /// Creates a sequence by concatenating source sequences until a source sequence completes successfully.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="sources">Source sequences.</param>
-        /// <returns>Sequence that continues to concatenate source sequences while errors occur.</returns>
-        public static IEnumerable<TSource> Catch<TSource>(this IEnumerable<IEnumerable<TSource>> sources)
-        {
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return sources.Catch_();
-        }
-
-        /// <summary>
-        /// Creates a sequence by concatenating source sequences until a source sequence completes successfully.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="sources">Source sequences.</param>
-        /// <returns>Sequence that continues to concatenate source sequences while errors occur.</returns>
-        public static IEnumerable<TSource> Catch<TSource>(params IEnumerable<TSource>[] sources)
-        {
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return sources.Catch_();
-        }
-
-        /// <summary>
-        /// Creates a sequence that returns the elements of the first sequence, switching to the second in case of an error.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="first">First sequence.</param>
-        /// <param name="second">Second sequence, concatenated to the result in case the first sequence completes exceptionally.</param>
-        /// <returns>The first sequence, followed by the second sequence in case an error is produced.</returns>
-        public static IEnumerable<TSource> Catch<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-
-            return new[] { first, second }.Catch_();
-        }
-
-        private static IEnumerable<TSource> Catch_<TSource>(this IEnumerable<IEnumerable<TSource>> sources)
-        {
-            var error = default(Exception);
-
-            foreach (var source in sources)
-            {
-                using (var e = source.GetEnumerator())
-                {
-                    error = null;
-
-                    while (true)
-                    {
-                        var c = default(TSource);
-
-                        try
-                        {
-                            if (!e.MoveNext())
-                                break;
-
-                            c = e.Current;
-                        }
-                        catch (Exception ex)
-                        {
-                            error = ex;
-                            break;
-                        }
-
-                        yield return c;
-                    }
-
-                    if (error == null)
-                        break;
-                }
-            }
-
-            if (error != null)
-                throw error;
-        }
-
-        /// <summary>
-        /// Creates a sequence whose termination or disposal of an enumerator causes a finally action to be executed.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="finallyAction">Action to run upon termination of the sequence, or when an enumerator is disposed.</param>
-        /// <returns>Source sequence with guarantees on the invocation of the finally action.</returns>
-        public static IEnumerable<TSource> Finally<TSource>(this IEnumerable<TSource> source, Action finallyAction)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (finallyAction == null)
-                throw new ArgumentNullException(nameof(finallyAction));
-
-            return source.Finally_(finallyAction);
-        }
-
-        private static IEnumerable<TSource> Finally_<TSource>(this IEnumerable<TSource> source, Action finallyAction)
-        {
-            try
-            {
-                foreach (var item in source)
-                    yield return item;
-            }
-            finally
-            {
-                finallyAction();
-            }
-        }
-
-        /// <summary>
-        /// Creates a sequence that concatenates both given sequences, regardless of whether an error occurs.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="first">First sequence.</param>
-        /// <param name="second">Second sequence.</param>
-        /// <returns>Sequence concatenating the elements of both sequences, ignoring errors.</returns>
-        public static IEnumerable<TSource> OnErrorResumeNext<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
-        {
-            if (first == null)
-                throw new ArgumentNullException(nameof(first));
-            if (second == null)
-                throw new ArgumentNullException(nameof(second));
-
-            return OnErrorResumeNext_(new[] { first, second });
-        }
-
-        /// <summary>
-        /// Creates a sequence that concatenates the given sequences, regardless of whether an error occurs in any of the sequences.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="sources">Source sequences.</param>
-        /// <returns>Sequence concatenating the elements of the given sequences, ignoring errors.</returns>
-        public static IEnumerable<TSource> OnErrorResumeNext<TSource>(params IEnumerable<TSource>[] sources)
-        {
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return OnErrorResumeNext_(sources);
-        }
-
-        /// <summary>
-        /// Creates a sequence that concatenates the given sequences, regardless of whether an error occurs in any of the sequences.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="sources">Source sequences.</param>
-        /// <returns>Sequence concatenating the elements of the given sequences, ignoring errors.</returns>
-        public static IEnumerable<TSource> OnErrorResumeNext<TSource>(this IEnumerable<IEnumerable<TSource>> sources)
-        {
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return OnErrorResumeNext_(sources);
-        }
-
-        private static IEnumerable<TSource> OnErrorResumeNext_<TSource>(IEnumerable<IEnumerable<TSource>> sources)
-        {
-            foreach (var source in sources)
-            {
-                using (var innerEnumerator = source.GetEnumerator())
-                {
-                    while (true)
-                    {
-                        var value = default(TSource);
-                        try
-                        {
-                            if (!innerEnumerator.MoveNext())
-                                break;
-                            value = innerEnumerator.Current;
-                        }
-                        catch
-                        {
-                            break;
-                        }
-
-                        yield return value;
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// Creates a sequence that retries enumerating the source sequence as long as an error occurs.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <returns>Sequence concatenating the results of the source sequence as long as an error occurs.</returns>
-        public static IEnumerable<TSource> Retry<TSource>(this IEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return new[] { source }.Repeat().Catch();
-        }
-
-        /// <summary>
-        /// Creates a sequence that retries enumerating the source sequence as long as an error occurs, with the specified maximum number of retries.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="retryCount">Maximum number of retries.</param>
-        /// <returns>Sequence concatenating the results of the source sequence as long as an error occurs.</returns>
-        public static IEnumerable<TSource> Retry<TSource>(this IEnumerable<TSource> source, int retryCount)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (retryCount < 0)
-                throw new ArgumentOutOfRangeException(nameof(retryCount));
-
-            return new[] { source }.Repeat(retryCount).Catch();
-        }
-    }
-}

+ 0 - 158
Ix.NET/Source/System.Interactive/EnumerableEx.Imperative.cs

@@ -1,158 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-
-namespace System.Linq
-{
-    public static partial class EnumerableEx
-    {
-        /// <summary>
-        /// Generates an enumerable sequence by repeating a source sequence as long as the given loop condition holds.
-        /// </summary>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="condition">Loop condition.</param>
-        /// <param name="source">Sequence to repeat while the condition evaluates true.</param>
-        /// <returns>Sequence generated by repeating the given sequence while the condition evaluates to true.</returns>
-        public static IEnumerable<TResult> While<TResult>(Func<bool> condition, IEnumerable<TResult> source)
-        {
-            if (condition == null)
-                throw new ArgumentNullException(nameof(condition));
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return WhileCore(condition, source).Concat();
-        }
-
-        static IEnumerable<IEnumerable<TSource>> WhileCore<TSource>(Func<bool> condition, IEnumerable<TSource> source)
-        {
-            while (condition())
-                yield return source;
-        }
-
-        /// <summary>
-        /// Returns an enumerable sequence based on the evaluation result of the given condition.
-        /// </summary>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="condition">Condition to evaluate.</param>
-        /// <param name="thenSource">Sequence to return in case the condition evaluates true.</param>
-        /// <param name="elseSource">Sequence to return in case the condition evaluates false.</param>
-        /// <returns>Either of the two input sequences based on the result of evaluating the condition.</returns>
-        public static IEnumerable<TResult> If<TResult>(Func<bool> condition, IEnumerable<TResult> thenSource, IEnumerable<TResult> elseSource)
-        {
-            if (condition == null)
-                throw new ArgumentNullException(nameof(condition));
-            if (thenSource == null)
-                throw new ArgumentNullException(nameof(thenSource));
-            if (elseSource == null)
-                throw new ArgumentNullException(nameof(elseSource));
-
-            return EnumerableEx.Defer(() => condition() ? thenSource : elseSource);
-        }
-
-        /// <summary>
-        /// Returns an enumerable sequence if the evaluation result of the given condition is true, otherwise returns an empty sequence.
-        /// </summary>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="condition">Condition to evaluate.</param>
-        /// <param name="thenSource">Sequence to return in case the condition evaluates true.</param>
-        /// <returns>The given input sequence if the condition evaluates true; otherwise, an empty sequence.</returns>
-        public static IEnumerable<TResult> If<TResult>(Func<bool> condition, IEnumerable<TResult> thenSource)
-        {
-            if (condition == null)
-                throw new ArgumentNullException(nameof(condition));
-            if (thenSource == null)
-                throw new ArgumentNullException(nameof(thenSource));
-
-            return EnumerableEx.Defer(() => condition() ? thenSource : Enumerable.Empty<TResult>());
-        }
-
-        /// <summary>
-        /// Generates an enumerable sequence by repeating a source sequence as long as the given loop postcondition holds.
-        /// </summary>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="source">Source sequence to repeat while the condition evaluates true.</param>
-        /// <param name="condition">Loop condition.</param>
-        /// <returns>Sequence generated by repeating the given sequence until the condition evaluates to false.</returns>
-        public static IEnumerable<TResult> DoWhile<TResult>(this IEnumerable<TResult> source, Func<bool> condition)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (condition == null)
-                throw new ArgumentNullException(nameof(condition));
-
-            return source.Concat(While(condition, source));
-        }
-
-        /// <summary>
-        /// Returns a sequence from a dictionary based on the result of evaluating a selector function.
-        /// </summary>
-        /// <typeparam name="TValue">Type of the selector value.</typeparam>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="selector">Selector function used to pick a sequence from the given sources.</param>
-        /// <param name="sources">Dictionary mapping selector values onto resulting sequences.</param>
-        /// <returns>The source sequence corresponding with the evaluated selector value; otherwise, an empty sequence.</returns>
-        public static IEnumerable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IEnumerable<TResult>> sources)
-        {
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return Case(selector, sources, Enumerable.Empty<TResult>());
-        }
-
-        /// <summary>
-        /// Returns a sequence from a dictionary based on the result of evaluating a selector function, also specifying a default sequence.
-        /// </summary>
-        /// <typeparam name="TValue">Type of the selector value.</typeparam>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="selector">Selector function used to pick a sequence from the given sources.</param>
-        /// <param name="sources">Dictionary mapping selector values onto resulting sequences.</param>
-        /// <param name="defaultSource">Default sequence to return in case there's no corresponding source for the computed selector value.</param>
-        /// <returns>The source sequence corresponding with the evaluated selector value; otherwise, the default source.</returns>
-        public static IEnumerable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IEnumerable<TResult>> sources, IEnumerable<TResult> defaultSource)
-        {
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-            if (defaultSource == null)
-                throw new ArgumentNullException(nameof(defaultSource));
-
-            return EnumerableEx.Defer(() =>
-            {
-                IEnumerable<TResult> result;
-                if (!sources.TryGetValue(selector(), out result))
-                    result = defaultSource;
-                return result;
-            });
-        }
-
-        /// <summary>
-        /// Generates a sequence by enumerating a source sequence, mapping its elements on result sequences, and concatenating those sequences.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TResult">Result sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="resultSelector">Result selector to evaluate for each iteration over the source.</param>
-        /// <returns>Sequence concatenating the inner sequences that result from evaluating the result selector on elements from the source.</returns>
-        public static IEnumerable<TResult> For<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> resultSelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (resultSelector == null)
-                throw new ArgumentNullException(nameof(resultSelector));
-
-            return ForCore(source, resultSelector).Concat();
-        }
-
-        static IEnumerable<IEnumerable<TResult>> ForCore<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> resultSelector)
-        {
-            return source.Select(resultSelector);
-        }
-    }
-}

+ 0 - 98
Ix.NET/Source/System.Interactive/EnumerableEx.Multiple.cs

@@ -1,98 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-
-namespace System.Linq
-{
-    public static partial class EnumerableEx
-    {
-        /// <summary>
-        /// Concatenates the input sequences.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="sources">Source sequences.</param>
-        /// <returns>Sequence with the elements of the source sequences concatenated.</returns>
-        public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<IEnumerable<TSource>> sources)
-        {
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return sources.Concat_();
-        }
-
-        /// <summary>
-        /// Concatenates the input sequences.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="sources">Source sequences.</param>
-        /// <returns>Sequence with the elements of the source sequences concatenated.</returns>
-        public static IEnumerable<TSource> Concat<TSource>(params IEnumerable<TSource>[] sources)
-        {
-            if (sources == null)
-                throw new ArgumentNullException(nameof(sources));
-
-            return sources.Concat_();
-        }
-
-        private static IEnumerable<TSource> Concat_<TSource>(this IEnumerable<IEnumerable<TSource>> sources)
-        {
-            foreach (var source in sources)
-                foreach (var item in source)
-                    yield return item;
-        }
-
-        /// <summary>
-        /// Projects each element of a sequence to an given sequence and flattens the resulting sequences into one sequence.
-        /// </summary>
-        /// <typeparam name="TSource">First source sequence element type.</typeparam>
-        /// <typeparam name="TOther">Second source sequence element type.</typeparam>
-        /// <param name="source">A sequence of values to project.</param>
-        /// <param name="other">Inner sequence each source sequenec element is projected onto.</param>
-        /// <returns>Sequence flattening the sequences that result from projecting elements in the source sequence.</returns>
-        public static IEnumerable<TOther> SelectMany<TSource, TOther>(this IEnumerable<TSource> source, IEnumerable<TOther> other)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (other == null)
-                throw new ArgumentNullException(nameof(other));
-
-            return source.SelectMany(_ => other);
-        }
-
-#if NO_ZIP
-        /// <summary>
-        /// Merges two sequences by applying the specified selector function on index-based corresponding element pairs from both sequences.
-        /// </summary>
-        /// <typeparam name="TFirst">The type of the elements of the first input sequence.</typeparam>
-        /// <typeparam name="TSecond">The type of the elements of the second input sequence.</typeparam>
-        /// <typeparam name="TResult">The type of the elements of the result sequence.</typeparam>
-        /// <param name="first">The first sequence to merge.</param>
-        /// <param name="second">The second sequence to merge.</param>
-        /// <param name="resultSelector">Function to apply to each pair of elements from both sequences.</param>
-        /// <returns>Sequence consisting of the result of pairwise application of the selector function over pairs of elements from the source sequences.</returns>
-        public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
-        {
-            if (first == null)
-                throw new ArgumentNullException("first");
-            if (second == null)
-                throw new ArgumentNullException("second");
-            if (resultSelector == null)
-                throw new ArgumentNullException("resultSelector");
-
-            return Zip_(first, second, resultSelector);
-        }
-
-        private static IEnumerable<TResult> Zip_<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
-        {
-            using (var e1 = first.GetEnumerator())
-            using (var e2 = second.GetEnumerator())
-                while (e1.MoveNext() && e2.MoveNext())
-                    yield return resultSelector(e1.Current, e2.Current);
-        }
-#endif
-    }
-}

+ 0 - 679
Ix.NET/Source/System.Interactive/EnumerableEx.Single.cs

@@ -1,679 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-
-namespace System.Linq
-{
-    public static partial class EnumerableEx
-    {
-        /// <summary>
-        /// Hides the enumerable sequence object identity.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <returns>Enumerable sequence with the same behavior as the original, but hiding the source object identity.</returns>
-        /// <remarks>AsEnumerable doesn't hide the object identity, and simply acts as a cast to the IEnumerable&lt;TSource&gt; interface.</remarks>
-        public static IEnumerable<TSource> Hide<TSource>(this IEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.Hide_();
-        }
-
-        private static IEnumerable<TSource> Hide_<TSource>(this IEnumerable<TSource> source)
-        {
-            foreach (var item in source)
-                yield return item;
-        }
-
-        /// <summary>
-        /// Enumerates the sequence and invokes the given action for each value in the sequence.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="onNext">Action to invoke for each element.</param>
-        public static void ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (onNext == null)
-                throw new ArgumentNullException(nameof(onNext));
-
-            foreach (var item in source)
-                onNext(item);
-        }
-
-        /// <summary>
-        /// Enumerates the sequence and invokes the given action for each value in the sequence.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="onNext">Action to invoke for each element.</param>
-        public static void ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource, int> onNext)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (onNext == null)
-                throw new ArgumentNullException(nameof(onNext));
-
-            var i = 0;
-            foreach (var item in source)
-                onNext(item, checked(i++));
-        }
-
-        /// <summary>
-        /// Lazily invokes an action for each value in the sequence.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="onNext">Action to invoke for each element.</param>
-        /// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
-        public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (onNext == null)
-                throw new ArgumentNullException(nameof(onNext));
-
-            return DoHelper(source, onNext, _ => { }, () => { });
-        }
-
-        /// <summary>
-        /// Lazily invokes an action for each value in the sequence, and executes an action for successful termination.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="onNext">Action to invoke for each element.</param>
-        /// <param name="onCompleted">Action to invoke on successful termination of the sequence.</param>
-        /// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
-        public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (onNext == null)
-                throw new ArgumentNullException(nameof(onNext));
-            if (onCompleted == null)
-                throw new ArgumentNullException(nameof(onCompleted));
-
-            return DoHelper(source, onNext, _ => { }, onCompleted);
-        }
-
-        /// <summary>
-        /// Lazily invokes an action for each value in the sequence, and executes an action upon exceptional termination.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="onNext">Action to invoke for each element.</param>
-        /// <param name="onError">Action to invoke on exceptional termination of the sequence.</param>
-        /// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
-        public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (onNext == null)
-                throw new ArgumentNullException(nameof(onNext));
-            if (onError == null)
-                throw new ArgumentNullException(nameof(onError));
-
-            return DoHelper(source, onNext, onError, () => { });
-        }
-
-        /// <summary>
-        /// Lazily invokes an action for each value in the sequence, and executes an action upon successful or exceptional termination.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="onNext">Action to invoke for each element.</param>
-        /// <param name="onError">Action to invoke on exceptional termination of the sequence.</param>
-        /// <param name="onCompleted">Action to invoke on successful termination of the sequence.</param>
-        /// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
-        public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (onNext == null)
-                throw new ArgumentNullException(nameof(onNext));
-            if (onError == null)
-                throw new ArgumentNullException(nameof(onError));
-            if (onCompleted == null)
-                throw new ArgumentNullException(nameof(onCompleted));
-
-            return DoHelper(source, onNext, onError, onCompleted);
-        }
-
-#if !NO_RXINTERFACES
-        /// <summary>
-        /// Lazily invokes observer methods for each value in the sequence, and upon successful or exceptional termination.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="observer">Observer to invoke notification calls on.</param>
-        /// <returns>Sequence exhibiting the side-effects of observer method invocation upon enumeration.</returns>
-        public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, IObserver<TSource> observer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (observer == null)
-                throw new ArgumentNullException(nameof(observer));
-
-            return DoHelper(source, observer.OnNext, observer.OnError, observer.OnCompleted);
-        }
-#endif
-
-        private static IEnumerable<TSource> DoHelper<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
-        {
-            using (var e = source.GetEnumerator())
-            {
-                while (true)
-                {
-                    var current = default(TSource);
-                    try
-                    {
-                        if (!e.MoveNext())
-                            break;
-
-                        current = e.Current;
-                    }
-                    catch (Exception ex)
-                    {
-                        onError(ex);
-                        throw;
-                    }
-
-                    onNext(current);
-                    yield return current;
-                }
-
-                onCompleted();
-            }
-        }
-
-        /// <summary>
-        /// Generates a sequence of non-overlapping adjacent buffers over the source sequence.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="count">Number of elements for allocated buffers.</param>
-        /// <returns>Sequence of buffers containing source sequence elements.</returns>
-        public static IEnumerable<IList<TSource>> Buffer<TSource>(this IEnumerable<TSource> source, int count)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (count <= 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-
-            return source.Buffer_(count, count);
-        }
-
-        /// <summary>
-        /// Generates a sequence of buffers over the source sequence, with specified length and possible overlap.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="count">Number of elements for allocated buffers.</param>
-        /// <param name="skip">Number of elements to skip between the start of consecutive buffers.</param>
-        /// <returns>Sequence of buffers containing source sequence elements.</returns>
-        public static IEnumerable<IList<TSource>> Buffer<TSource>(this IEnumerable<TSource> source, int count, int skip)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (count <= 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-            if (skip <= 0)
-                throw new ArgumentOutOfRangeException(nameof(skip));
-
-            return source.Buffer_(count, skip);
-        }
-
-        private static IEnumerable<IList<TSource>> Buffer_<TSource>(this IEnumerable<TSource> source, int count, int skip)
-        {
-            var buffers = new Queue<IList<TSource>>();
-
-            var i = 0;
-            foreach (var item in source)
-            {
-                if (i % skip == 0)
-                    buffers.Enqueue(new List<TSource>(count));
-
-                foreach (var buffer in buffers)
-                    buffer.Add(item);
-
-                if (buffers.Count > 0 && buffers.Peek().Count == count)
-                    yield return buffers.Dequeue();
-
-                i++;
-            }
-
-            while (buffers.Count > 0)
-                yield return buffers.Dequeue();
-        }
-
-        /// <summary>
-        /// Ignores all elements in the source sequence.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <returns>Source sequence without its elements.</returns>
-        public static IEnumerable<TSource> IgnoreElements<TSource>(this IEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.IgnoreElements_();
-        }
-
-        private static IEnumerable<TSource> IgnoreElements_<TSource>(this IEnumerable<TSource> source)
-        {
-            foreach (var item in source)
-                ;
-
-            yield break;
-        }
-
-        /// <summary>
-        /// Returns elements with a distinct key value by using the default equality comparer to compare key values.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TKey">Key type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="keySelector">Key selector.</param>
-        /// <returns>Sequence that contains the elements from the source sequence with distinct key values.</returns>
-        public static IEnumerable<TSource> Distinct<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return source.Distinct_(keySelector, EqualityComparer<TKey>.Default);
-        }
-
-        /// <summary>
-        /// Returns elements with a distinct key value by using the specified equality comparer to compare key values.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TKey">Key type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="keySelector">Key selector.</param>
-        /// <param name="comparer">Comparer used to compare key values.</param>
-        /// <returns>Sequence that contains the elements from the source sequence with distinct key values.</returns>
-        public static IEnumerable<TSource> Distinct<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.Distinct_(keySelector, comparer);
-        }
-
-        private static IEnumerable<TSource> Distinct_<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
-        {
-            var set = new HashSet<TKey>(comparer);
-
-            foreach (var item in source)
-            {
-                var key = keySelector(item);
-                if (set.Add(key))
-                    yield return item;
-            }
-        }
-
-#if NO_HASHSET
-        class HashSet<T>
-        {
-            private Dictionary<T, object> _set;
-
-            public HashSet(IEqualityComparer<T> comparer)
-            {
-                _set = new Dictionary<T, object>(comparer);
-            }
-
-            public bool Add(T value)
-            {
-                if (_set.ContainsKey(value))
-                    return false;
-
-                _set[value] = null;
-                return true;
-            }
-        }
-#endif
-
-        /// <summary>
-        /// Returns consecutive distinct elements by using the default equality comparer to compare values.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <returns>Sequence without adjacent non-distinct elements.</returns>
-        public static IEnumerable<TSource> DistinctUntilChanged<TSource>(this IEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.DistinctUntilChanged_(x => x, EqualityComparer<TSource>.Default);
-        }
-
-        /// <summary>
-        /// Returns consecutive distinct elements by using the specified equality comparer to compare values.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="comparer">Comparer used to compare values.</param>
-        /// <returns>Sequence without adjacent non-distinct elements.</returns>
-        public static IEnumerable<TSource> DistinctUntilChanged<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.DistinctUntilChanged_(x => x, comparer);
-        }
-
-        /// <summary>
-        /// Returns consecutive distinct elements based on a key value by using the specified equality comparer to compare key values.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TKey">Key type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="keySelector">Key selector.</param>
-        /// <returns>Sequence without adjacent non-distinct elements.</returns>
-        public static IEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-
-            return source.DistinctUntilChanged_(keySelector, EqualityComparer<TKey>.Default);
-        }
-
-        /// <summary>
-        /// Returns consecutive distinct elements based on a key value by using the specified equality comparer to compare key values.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TKey">Key type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="keySelector">Key selector.</param>
-        /// <param name="comparer">Comparer used to compare key values.</param>
-        /// <returns>Sequence without adjacent non-distinct elements.</returns>
-        public static IEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (keySelector == null)
-                throw new ArgumentNullException(nameof(keySelector));
-            if (comparer == null)
-                throw new ArgumentNullException(nameof(comparer));
-
-            return source.DistinctUntilChanged_(keySelector, comparer);
-        }
-
-        private static IEnumerable<TSource> DistinctUntilChanged_<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
-        {
-            var currentKey = default(TKey);
-            var hasCurrentKey = false;
-
-            foreach (var item in source)
-            {
-                var key = keySelector(item);
-
-                var comparerEquals = false;
-                if (hasCurrentKey)
-                {
-                    comparerEquals = comparer.Equals(currentKey, key);
-                }
-
-                if (!hasCurrentKey || !comparerEquals)
-                {
-                    hasCurrentKey = true;
-                    currentKey = key;
-                    yield return item;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Expands the sequence by recursively applying a selector function.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="selector">Selector function to retrieve the next sequence to expand.</param>
-        /// <returns>Sequence with results from the recursive expansion of the source sequence.</returns>
-        public static IEnumerable<TSource> Expand<TSource>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TSource>> selector)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (selector == null)
-                throw new ArgumentNullException(nameof(selector));
-
-            return source.Expand_(selector);
-        }
-
-        private static IEnumerable<TSource> Expand_<TSource>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TSource>> selector)
-        {
-            var queue = new Queue<IEnumerable<TSource>>();
-            queue.Enqueue(source);
-
-            while (queue.Count > 0)
-            {
-                var src = queue.Dequeue();
-
-                foreach (var item in src)
-                {
-                    queue.Enqueue(selector(item));
-                    yield return item;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Returns the source sequence prefixed with the specified value.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="values">Values to prefix the sequence with.</param>
-        /// <returns>Sequence starting with the specified prefix value, followed by the source sequence.</returns>
-        public static IEnumerable<TSource> StartWith<TSource>(this IEnumerable<TSource> source, params TSource[] values)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return source.StartWith_(values);
-        }
-
-        private static IEnumerable<TSource> StartWith_<TSource>(this IEnumerable<TSource> source, params TSource[] values)
-        {
-            foreach (var x in values)
-                yield return x;
-
-            foreach (var item in source)
-                yield return item;
-        }
-
-        /// <summary>
-        /// Generates a sequence of accumulated values by scanning the source sequence and applying an accumulator function.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <typeparam name="TAccumulate">Accumulation type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="seed">Accumulator seed value.</param>
-        /// <param name="accumulator">Accumulation function to apply to the current accumulation value and each element of the sequence.</param>
-        /// <returns>Sequence with all intermediate accumulation values resulting from scanning the sequence.</returns>
-        public static IEnumerable<TAccumulate> Scan<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (accumulator == null)
-                throw new ArgumentNullException(nameof(accumulator));
-
-            return source.Scan_(seed, accumulator);
-        }
-
-        private static IEnumerable<TAccumulate> Scan_<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
-        {
-            var acc = seed;
-
-            foreach (var item in source)
-            {
-                acc = accumulator(acc, item);
-                yield return acc;
-            }
-        }
-
-        /// <summary>
-        /// Generates a sequence of accumulated values by scanning the source sequence and applying an accumulator function.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="accumulator">Accumulation function to apply to the current accumulation value and each element of the sequence.</param>
-        /// <returns>Sequence with all intermediate accumulation values resulting from scanning the sequence.</returns>
-        public static IEnumerable<TSource> Scan<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (accumulator == null)
-                throw new ArgumentNullException(nameof(accumulator));
-
-            return source.Scan_(accumulator);
-        }
-
-        private static IEnumerable<TSource> Scan_<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator)
-        {
-            var hasSeed = false;
-            var acc = default(TSource);
-
-            foreach (var item in source)
-            {
-                if (!hasSeed)
-                {
-                    hasSeed = true;
-                    acc = item;
-                    continue;
-                }
-
-                acc = accumulator(acc, item);
-                yield return acc;
-            }
-        }
-
-        /// <summary>
-        /// Returns a specified number of contiguous elements from the end of the sequence.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="count">The number of elements to take from the end of the sequence.</param>
-        /// <returns>Sequence with the specified number of elements counting from the end of the source sequence.</returns>
-        public static IEnumerable<TSource> TakeLast<TSource>(this IEnumerable<TSource> source, int count)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (count < 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-
-            return source.TakeLast_(count);
-        }
-
-        private static IEnumerable<TSource> TakeLast_<TSource>(this IEnumerable<TSource> source, int count)
-        {
-            if (count == 0)
-            {
-                yield break;
-            }
-
-            var q = new Queue<TSource>(count);
-
-            foreach (var item in source)
-            {
-                if (q.Count >= count)
-                    q.Dequeue();
-                q.Enqueue(item);
-            }
-
-            while (q.Count > 0)
-                yield return q.Dequeue();
-        }
-
-        /// <summary>
-        /// Bypasses a specified number of contiguous elements from the end of the sequence and returns the remaining elements.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="count">The number of elements to skip from the end of the sequence before returning the remaining elements.</param>
-        /// <returns>Sequence bypassing the specified number of elements counting from the end of the source sequence.</returns>
-        public static IEnumerable<TSource> SkipLast<TSource>(this IEnumerable<TSource> source, int count)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (count < 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-
-            return source.SkipLast_(count);
-        }
-
-        private static IEnumerable<TSource> SkipLast_<TSource>(this IEnumerable<TSource> source, int count)
-        {
-            var q = new Queue<TSource>();
-
-            foreach (var x in source)
-            {
-                q.Enqueue(x);
-                if (q.Count > count)
-                    yield return q.Dequeue();
-            }
-        }
-
-        /// <summary>
-        /// Repeats and concatenates the source sequence infinitely.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <returns>Sequence obtained by concatenating the source sequence to itself infinitely.</returns>
-        public static IEnumerable<TSource> Repeat<TSource>(this IEnumerable<TSource> source)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-
-            return Repeat_(source);
-        }
-
-        private static IEnumerable<TSource> Repeat_<TSource>(IEnumerable<TSource> source)
-        {
-            while (true)
-                foreach (var item in source)
-                    yield return item;
-        }
-
-        /// <summary>
-        /// Repeats and concatenates the source sequence the given number of times.
-        /// </summary>
-        /// <typeparam name="TSource">Source sequence element type.</typeparam>
-        /// <param name="source">Source sequence.</param>
-        /// <param name="count">Number of times to repeat the source sequence.</param>
-        /// <returns>Sequence obtained by concatenating the source sequence to itself the specified number of times.</returns>
-        public static IEnumerable<TSource> Repeat<TSource>(this IEnumerable<TSource> source, int count)
-        {
-            if (source == null)
-                throw new ArgumentNullException(nameof(source));
-            if (count < 0)
-                throw new ArgumentOutOfRangeException(nameof(count));
-
-            return Repeat_(source, count);
-        }
-
-        private static IEnumerable<TSource> Repeat_<TSource>(IEnumerable<TSource> source, int count)
-        {
-            for (var i = 0; i < count; i++)
-                foreach (var item in source)
-                    yield return item;
-        }
-    }
-}

+ 48 - 0
Ix.NET/Source/System.Interactive/Expand.cs

@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Expands the sequence by recursively applying a selector function.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="selector">Selector function to retrieve the next sequence to expand.</param>
+        /// <returns>Sequence with results from the recursive expansion of the source sequence.</returns>
+        public static IEnumerable<TSource> Expand<TSource>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TSource>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return source.Expand_(selector);
+        }
+
+        private static IEnumerable<TSource> Expand_<TSource>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TSource>> selector)
+        {
+            var queue = new Queue<IEnumerable<TSource>>();
+            queue.Enqueue(source);
+
+            while (queue.Count > 0)
+            {
+                var src = queue.Dequeue();
+
+                foreach (var item in src)
+                {
+                    queue.Enqueue(selector(item));
+                    yield return item;
+                }
+            }
+        }
+    }
+}

+ 44 - 0
Ix.NET/Source/System.Interactive/Finally.cs

@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Creates a sequence whose termination or disposal of an enumerator causes a finally action to be executed.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="finallyAction">Action to run upon termination of the sequence, or when an enumerator is disposed.</param>
+        /// <returns>Source sequence with guarantees on the invocation of the finally action.</returns>
+        public static IEnumerable<TSource> Finally<TSource>(this IEnumerable<TSource> source, Action finallyAction)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (finallyAction == null)
+                throw new ArgumentNullException(nameof(finallyAction));
+
+            return source.Finally_(finallyAction);
+        }
+
+        private static IEnumerable<TSource> Finally_<TSource>(this IEnumerable<TSource> source, Action finallyAction)
+        {
+            try
+            {
+                foreach (var item in source)
+                    yield return item;
+            }
+            finally
+            {
+                finallyAction();
+            }
+        }
+    }
+}

+ 42 - 0
Ix.NET/Source/System.Interactive/For.cs

@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Generates a sequence by enumerating a source sequence, mapping its elements on result sequences, and concatenating
+        ///     those sequences.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="resultSelector">Result selector to evaluate for each iteration over the source.</param>
+        /// <returns>
+        ///     Sequence concatenating the inner sequences that result from evaluating the result selector on elements from
+        ///     the source.
+        /// </returns>
+        public static IEnumerable<TResult> For<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> resultSelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+
+            return ForCore(source, resultSelector)
+                .Concat();
+        }
+
+        private static IEnumerable<IEnumerable<TResult>> ForCore<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> resultSelector)
+        {
+            return source.Select(resultSelector);
+        }
+    }
+}

+ 49 - 0
Ix.NET/Source/System.Interactive/ForEach.cs

@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Enumerates the sequence and invokes the given action for each value in the sequence.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="onNext">Action to invoke for each element.</param>
+        public static void ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            foreach (var item in source)
+                onNext(item);
+        }
+
+        /// <summary>
+        ///     Enumerates the sequence and invokes the given action for each value in the sequence.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="onNext">Action to invoke for each element.</param>
+        public static void ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource, int> onNext)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (onNext == null)
+                throw new ArgumentNullException(nameof(onNext));
+
+            var i = 0;
+            foreach (var item in source)
+                onNext(item, checked(i++));
+        }
+    }
+}

+ 42 - 0
Ix.NET/Source/System.Interactive/Generate.cs

@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Generates a sequence by mimicking a for loop.
+        /// </summary>
+        /// <typeparam name="TState">State type.</typeparam>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="initialState">Initial state of the generator loop.</param>
+        /// <param name="condition">Loop condition.</param>
+        /// <param name="iterate">State update function to run after every iteration of the generator loop.</param>
+        /// <param name="resultSelector">Result selector to compute resulting sequence elements.</param>
+        /// <returns>Sequence obtained by running the generator loop, yielding computed elements.</returns>
+        public static IEnumerable<TResult> Generate<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector)
+        {
+            if (condition == null)
+                throw new ArgumentNullException(nameof(condition));
+            if (iterate == null)
+                throw new ArgumentNullException(nameof(iterate));
+            if (resultSelector == null)
+                throw new ArgumentNullException(nameof(resultSelector));
+
+            return Generate_(initialState, condition, iterate, resultSelector);
+        }
+
+        private static IEnumerable<TResult> Generate_<TState, TResult>(TState initialState, Func<TState, bool> condition, Func<TState, TState> iterate, Func<TState, TResult> resultSelector)
+        {
+            for (var i = initialState; condition(i); i = iterate(i))
+                yield return resultSelector(i);
+        }
+    }
+}

+ 38 - 0
Ix.NET/Source/System.Interactive/Hide.cs

@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Hides the enumerable sequence object identity.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <returns>Enumerable sequence with the same behavior as the original, but hiding the source object identity.</returns>
+        /// <remarks>
+        ///     AsEnumerable doesn't hide the object identity, and simply acts as a cast to the IEnumerable&lt;TSource&gt;
+        ///     interface.
+        /// </remarks>
+        public static IEnumerable<TSource> Hide<TSource>(this IEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.Hide_();
+        }
+
+        private static IEnumerable<TSource> Hide_<TSource>(this IEnumerable<TSource> source)
+        {
+            foreach (var item in source)
+                yield return item;
+        }
+    }
+}

+ 43 - 45
Ix.NET/Source/System.Interactive/IYielder.cs

@@ -1,49 +1,79 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the Apache 2.0 License.
 // See the LICENSE file in the project root for more information. 
-#if HAS_AWAIT
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
 using System.Security;
+using System.Threading.Tasks;
 
 namespace System.Linq
 {
     /// <summary>
-    /// Interface for yielding elements to enumerator.
+    ///     Interface for yielding elements to enumerator.
     /// </summary>
     /// <typeparam name="T">Type of the elements yielded to an enumerator.</typeparam>
     public interface IYielder<in T>
     {
         /// <summary>
-        /// Yields a value to the enumerator.
+        ///     Stops the enumeration.
         /// </summary>
-        /// <param name="value">Value to yield return.</param>
         /// <returns>Awaitable object for use in an asynchronous method.</returns>
-        IAwaitable Return(T value);
+        IAwaitable Break();
 
         /// <summary>
-        /// Stops the enumeration.
+        ///     Yields a value to the enumerator.
         /// </summary>
+        /// <param name="value">Value to yield return.</param>
         /// <returns>Awaitable object for use in an asynchronous method.</returns>
-        IAwaitable Break();
+        IAwaitable Return(T value);
     }
 
-    class Yielder<T> : IYielder<T>, IAwaitable, IAwaiter
+    internal class Yielder<T> : IYielder<T>, IAwaitable, IAwaiter
     {
         private readonly Action<Yielder<T>> _create;
-        private bool _running;
+        private Action _continuation;
         private bool _hasValue;
-        private T _value;
+        private bool _running;
         private bool _stopped;
-        private Action _continuation;
 
         public Yielder(Action<Yielder<T>> create)
         {
             _create = create;
         }
 
+        public T Current { get; private set; }
+
+        public IAwaiter GetAwaiter()
+        {
+            return this;
+        }
+
+        public bool IsCompleted
+        {
+            get { return false; }
+        }
+
+        public void GetResult()
+        {
+        }
+
+        [SecurityCritical]
+        public void UnsafeOnCompleted(Action continuation)
+        {
+            _continuation = continuation;
+        }
+
+        public void OnCompleted(Action continuation)
+        {
+            _continuation = continuation;
+        }
+
         public IAwaitable Return(T value)
         {
             _hasValue = true;
-            _value = value;
+            Current = value;
             return this;
         }
 
@@ -74,41 +104,9 @@ namespace System.Linq
             return !_stopped && _hasValue;
         }
 
-        public T Current
-        {
-            get
-            {
-                return _value;
-            }
-        }
-
         public void Reset()
         {
             throw new NotSupportedException();
         }
-
-        public IAwaiter GetAwaiter()
-        {
-            return this;
-        }
-
-        public bool IsCompleted
-        {
-            get { return false; }
-        }
-
-        public void GetResult() { }
-
-        [SecurityCritical]
-        public void UnsafeOnCompleted(Action continuation)
-        {
-            _continuation = continuation;
-        }
-
-        public void OnCompleted(Action continuation)
-        {
-            _continuation = continuation;
-        }
     }
-}
-#endif
+}

+ 52 - 0
Ix.NET/Source/System.Interactive/If.cs

@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Returns an enumerable sequence based on the evaluation result of the given condition.
+        /// </summary>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="condition">Condition to evaluate.</param>
+        /// <param name="thenSource">Sequence to return in case the condition evaluates true.</param>
+        /// <param name="elseSource">Sequence to return in case the condition evaluates false.</param>
+        /// <returns>Either of the two input sequences based on the result of evaluating the condition.</returns>
+        public static IEnumerable<TResult> If<TResult>(Func<bool> condition, IEnumerable<TResult> thenSource, IEnumerable<TResult> elseSource)
+        {
+            if (condition == null)
+                throw new ArgumentNullException(nameof(condition));
+            if (thenSource == null)
+                throw new ArgumentNullException(nameof(thenSource));
+            if (elseSource == null)
+                throw new ArgumentNullException(nameof(elseSource));
+
+            return Defer(() => condition() ? thenSource : elseSource);
+        }
+
+        /// <summary>
+        ///     Returns an enumerable sequence if the evaluation result of the given condition is true, otherwise returns an empty
+        ///     sequence.
+        /// </summary>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="condition">Condition to evaluate.</param>
+        /// <param name="thenSource">Sequence to return in case the condition evaluates true.</param>
+        /// <returns>The given input sequence if the condition evaluates true; otherwise, an empty sequence.</returns>
+        public static IEnumerable<TResult> If<TResult>(Func<bool> condition, IEnumerable<TResult> thenSource)
+        {
+            if (condition == null)
+                throw new ArgumentNullException(nameof(condition));
+            if (thenSource == null)
+                throw new ArgumentNullException(nameof(thenSource));
+
+            return Defer(() => condition() ? thenSource : Enumerable.Empty<TResult>());
+        }
+    }
+}

+ 36 - 0
Ix.NET/Source/System.Interactive/IgnoreElements.cs

@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Ignores all elements in the source sequence.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <returns>Source sequence without its elements.</returns>
+        public static IEnumerable<TSource> IgnoreElements<TSource>(this IEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.IgnoreElements_();
+        }
+
+        private static IEnumerable<TSource> IgnoreElements_<TSource>(this IEnumerable<TSource> source)
+        {
+            foreach (var item in source)
+            ;
+
+            yield break;
+        }
+    }
+}

+ 108 - 0
Ix.NET/Source/System.Interactive/Max.cs

@@ -0,0 +1,108 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Returns the maximum value in the enumerable sequence by using the specified comparer to compare values.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="comparer">Comparer used to determine the maximum value.</param>
+        /// <returns>Maximum value in the sequence.</returns>
+        public static TSource Max<TSource>(this IEnumerable<TSource> source, IComparer<TSource> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return MaxBy(source, x => x, comparer)
+                .First();
+        }
+
+        /// <summary>
+        ///     Returns the elements with the maximum key value by using the default comparer to compare key values.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TKey">Key type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="keySelector">Key selector used to extract the key for each element in the sequence.</param>
+        /// <returns>List with the elements that share the same maximum key value.</returns>
+        public static IList<TSource> MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return MaxBy(source, keySelector, Comparer<TKey>.Default);
+        }
+
+        /// <summary>
+        ///     Returns the elements with the minimum key value by using the specified comparer to compare key values.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TKey">Key type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="keySelector">Key selector used to extract the key for each element in the sequence.</param>
+        /// <param name="comparer">Comparer used to determine the maximum key value.</param>
+        /// <returns>List with the elements that share the same maximum key value.</returns>
+        public static IList<TSource> MaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return ExtremaBy(source, keySelector, (key, minValue) => comparer.Compare(key, minValue));
+        }
+
+        private static IList<TSource> ExtremaBy<TSource, TKey>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, TKey, int> compare)
+        {
+            var result = new List<TSource>();
+
+            using (var e = source.GetEnumerator())
+            {
+                if (!e.MoveNext())
+                    throw new InvalidOperationException("Source sequence doesn't contain any elements.");
+
+                var current = e.Current;
+                var resKey = keySelector(current);
+                result.Add(current);
+
+                while (e.MoveNext())
+                {
+                    var cur = e.Current;
+                    var key = keySelector(cur);
+
+                    var cmp = compare(key, resKey);
+                    if (cmp == 0)
+                    {
+                        result.Add(cur);
+                    }
+                    else if (cmp > 0)
+                    {
+                        result = new List<TSource>
+                        {
+                            cur
+                        };
+                        resKey = key;
+                    }
+                }
+            }
+
+            return result;
+        }
+    }
+}

+ 370 - 0
Ix.NET/Source/System.Interactive/Memoize.cs

@@ -0,0 +1,370 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Creates a buffer with a view over the source sequence, causing each enumerator to obtain access to all of the
+        ///     sequence's elements without causing multiple enumerations over the source.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <returns>
+        ///     Buffer enabling each enumerator to retrieve all elements from the shared source sequence, without duplicating
+        ///     source enumeration side-effects.
+        /// </returns>
+        /// <example>
+        ///     var rng = Enumerable.Range(0, 10).Do(x => Console.WriteLine(x)).Memoize();
+        ///     var e1 = rng.GetEnumerator();
+        ///     Assert.IsTrue(e1.MoveNext());    // Prints 0
+        ///     Assert.AreEqual(0, e1.Current);
+        ///     Assert.IsTrue(e1.MoveNext());    // Prints 1
+        ///     Assert.AreEqual(1, e1.Current);
+        ///     var e2 = rng.GetEnumerator();
+        ///     Assert.IsTrue(e2.MoveNext());    // Doesn't print anything; the side-effect of Do
+        ///     Assert.AreEqual(0, e2.Current);  // has already taken place during e1's iteration.
+        ///     Assert.IsTrue(e1.MoveNext());    // Prints 2
+        ///     Assert.AreEqual(2, e1.Current);
+        /// </example>
+        public static IBuffer<TSource> Memoize<TSource>(this IEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return new MemoizedBuffer<TSource>(source.GetEnumerator());
+        }
+
+        /// <summary>
+        ///     Memoizes the source sequence within a selector function where each enumerator can get access to all of the
+        ///     sequence's elements without causing multiple enumerations over the source.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="selector">Selector function with memoized access to the source sequence for each enumerator.</param>
+        /// <returns>Sequence resulting from applying the selector function to the memoized view over the source sequence.</returns>
+        public static IEnumerable<TResult> Memoize<TSource, TResult>(this IEnumerable<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create(() => selector(source.Memoize())
+                              .GetEnumerator());
+        }
+
+        /// <summary>
+        ///     Creates a buffer with a view over the source sequence, causing a specified number of enumerators to obtain access
+        ///     to all of the sequence's elements without causing multiple enumerations over the source.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="readerCount">
+        ///     Number of enumerators that can access the underlying buffer. Once every enumerator has
+        ///     obtained an element from the buffer, the element is removed from the buffer.
+        /// </param>
+        /// <returns>
+        ///     Buffer enabling a specified number of enumerators to retrieve all elements from the shared source sequence,
+        ///     without duplicating source enumeration side-effects.
+        /// </returns>
+        public static IBuffer<TSource> Memoize<TSource>(this IEnumerable<TSource> source, int readerCount)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (readerCount <= 0)
+                throw new ArgumentOutOfRangeException(nameof(readerCount));
+
+            return new MemoizedBuffer<TSource>(source.GetEnumerator(), readerCount);
+        }
+
+        /// <summary>
+        ///     Memoizes the source sequence within a selector function where a specified number of enumerators can get access to
+        ///     all of the sequence's elements without causing multiple enumerations over the source.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="readerCount">
+        ///     Number of enumerators that can access the underlying buffer. Once every enumerator has
+        ///     obtained an element from the buffer, the element is removed from the buffer.
+        /// </param>
+        /// <param name="selector">
+        ///     Selector function with memoized access to the source sequence for a specified number of
+        ///     enumerators.
+        /// </param>
+        /// <returns>Sequence resulting from applying the selector function to the memoized view over the source sequence.</returns>
+        public static IEnumerable<TResult> Memoize<TSource, TResult>(this IEnumerable<TSource> source, int readerCount, Func<IEnumerable<TSource>, IEnumerable<TResult>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (readerCount <= 0)
+                throw new ArgumentOutOfRangeException(nameof(readerCount));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create(() => selector(source.Memoize(readerCount))
+                              .GetEnumerator());
+        }
+
+        private class MemoizedBuffer<T> : IBuffer<T>
+        {
+            private IRefCountList<T> _buffer;
+            private bool _disposed;
+            private Exception _error;
+            private IEnumerator<T> _source;
+            private bool _stopped;
+
+            public MemoizedBuffer(IEnumerator<T> source)
+                : this(source, new MaxRefCountList<T>())
+            {
+            }
+
+            public MemoizedBuffer(IEnumerator<T> source, int readerCount)
+                : this(source, new RefCountList<T>(readerCount))
+            {
+            }
+
+            private MemoizedBuffer(IEnumerator<T> source, IRefCountList<T> buffer)
+            {
+                _source = source;
+                _buffer = buffer;
+            }
+
+            public IEnumerator<T> GetEnumerator()
+            {
+                if (_disposed)
+                    throw new ObjectDisposedException("");
+
+                return GetEnumerator_();
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                if (_disposed)
+                    throw new ObjectDisposedException("");
+
+                return GetEnumerator();
+            }
+
+            public void Dispose()
+            {
+                lock (_source)
+                {
+                    if (!_disposed)
+                    {
+                        _source.Dispose();
+                        _source = null;
+
+                        _buffer.Clear();
+                        _buffer = null;
+                    }
+
+                    _disposed = true;
+                }
+            }
+
+            private IEnumerator<T> GetEnumerator_()
+            {
+                var i = 0;
+
+                try
+                {
+                    while (true)
+                    {
+                        if (_disposed)
+                            throw new ObjectDisposedException("");
+
+                        var hasValue = default(bool);
+                        var current = default(T);
+
+                        lock (_source)
+                        {
+                            if (i >= _buffer.Count)
+                            {
+                                if (!_stopped)
+                                {
+                                    try
+                                    {
+                                        hasValue = _source.MoveNext();
+                                        if (hasValue)
+                                            current = _source.Current;
+                                    }
+                                    catch (Exception ex)
+                                    {
+                                        _stopped = true;
+                                        _error = ex;
+
+                                        _source.Dispose();
+                                    }
+                                }
+
+                                if (_stopped)
+                                {
+                                    if (_error != null)
+                                        throw _error;
+                                    else
+                                        break;
+                                }
+
+                                if (hasValue)
+                                {
+                                    _buffer.Add(current);
+                                }
+                            }
+                            else
+                            {
+                                hasValue = true;
+                            }
+                        }
+
+                        if (hasValue)
+                            yield return _buffer[i];
+                        else
+                            break;
+
+                        i++;
+                    }
+                }
+                finally
+                {
+                    if (_buffer != null)
+                        _buffer.Done(i + 1);
+                }
+            }
+        }
+    }
+
+
+
+    interface IRefCountList<T>
+    {
+        void Clear();
+
+        int Count { get; }
+
+        T this[int i]
+        {
+            get;
+        }
+
+        void Add(T item);
+
+        void Done(int index);
+    }
+
+    class MaxRefCountList<T> : IRefCountList<T>
+    {
+        private IList<T> _list = new List<T>();
+
+        public void Clear()
+        {
+            _list.Clear();
+        }
+
+        public int Count
+        {
+            get { return _list.Count; }
+        }
+
+        public T this[int i]
+        {
+            get { return _list[i]; }
+        }
+
+        public void Add(T item)
+        {
+            _list.Add(item);
+        }
+
+        public void Done(int index)
+        {
+        }
+    }
+
+    class RefCountList<T> : IRefCountList<T>
+    {
+        private int _readerCount;
+        private readonly IDictionary<int, RefCount> _list;
+        private int _count;
+
+        public RefCountList(int readerCount)
+        {
+            _readerCount = readerCount;
+            _list = new Dictionary<int, RefCount>();
+        }
+
+        public int ReaderCount
+        {
+            get
+            {
+                return _readerCount;
+            }
+
+            set
+            {
+                _readerCount = value;
+            }
+        }
+
+        public void Clear()
+        {
+            _list.Clear();
+        }
+
+        public int Count
+        {
+            get { return _count; }
+        }
+
+        public T this[int i]
+        {
+            get
+            {
+                Debug.Assert(i < _count);
+
+                var res = default(RefCount);
+                if (!_list.TryGetValue(i, out res))
+                    throw new InvalidOperationException("Element no longer available in the buffer.");
+
+                var val = res.Value;
+                if (--res.Count == 0)
+                    _list.Remove(i);
+
+                return val;
+            }
+        }
+
+        public void Add(T item)
+        {
+            _list[_count] = new RefCount { Value = item, Count = _readerCount };
+            _count++;
+        }
+
+        public void Done(int index)
+        {
+            for (int i = index; i < _count; i++)
+            {
+                var ignore = this[i];
+            }
+
+            _readerCount--;
+        }
+
+        class RefCount
+        {
+            public int Count;
+            public T Value;
+        }
+    }
+}

+ 71 - 0
Ix.NET/Source/System.Interactive/Min.cs

@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Returns the minimum value in the enumerable sequence by using the specified comparer to compare values.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="comparer">Comparer used to determine the minimum value.</param>
+        /// <returns>Minimum value in the sequence.</returns>
+        public static TSource Min<TSource>(this IEnumerable<TSource> source, IComparer<TSource> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return MinBy(source, x => x, comparer)
+                .First();
+        }
+
+        /// <summary>
+        ///     Returns the elements with the minimum key value by using the default comparer to compare key values.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TKey">Key type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="keySelector">Key selector used to extract the key for each element in the sequence.</param>
+        /// <returns>List with the elements that share the same minimum key value.</returns>
+        public static IList<TSource> MinBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+
+            return MinBy(source, keySelector, Comparer<TKey>.Default);
+        }
+
+        /// <summary>
+        ///     Returns the elements with the minimum key value by using the specified comparer to compare key values.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TKey">Key type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="keySelector">Key selector used to extract the key for each element in the sequence.</param>
+        /// <param name="comparer">Comparer used to determine the minimum key value.</param>
+        /// <returns>List with the elements that share the same minimum key value.</returns>
+        public static IList<TSource> MinBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (keySelector == null)
+                throw new ArgumentNullException(nameof(keySelector));
+            if (comparer == null)
+                throw new ArgumentNullException(nameof(comparer));
+
+            return ExtremaBy(source, keySelector, (key, minValue) => -comparer.Compare(key, minValue));
+        }
+    }
+}

+ 87 - 0
Ix.NET/Source/System.Interactive/OnErrorResumeNext.cs

@@ -0,0 +1,87 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Creates a sequence that concatenates both given sequences, regardless of whether an error occurs.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="first">First sequence.</param>
+        /// <param name="second">Second sequence.</param>
+        /// <returns>Sequence concatenating the elements of both sequences, ignoring errors.</returns>
+        public static IEnumerable<TSource> OnErrorResumeNext<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
+        {
+            if (first == null)
+                throw new ArgumentNullException(nameof(first));
+            if (second == null)
+                throw new ArgumentNullException(nameof(second));
+
+            return OnErrorResumeNext_(new[] {first, second});
+        }
+
+        /// <summary>
+        ///     Creates a sequence that concatenates the given sequences, regardless of whether an error occurs in any of the
+        ///     sequences.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="sources">Source sequences.</param>
+        /// <returns>Sequence concatenating the elements of the given sequences, ignoring errors.</returns>
+        public static IEnumerable<TSource> OnErrorResumeNext<TSource>(params IEnumerable<TSource>[] sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return OnErrorResumeNext_(sources);
+        }
+
+        /// <summary>
+        ///     Creates a sequence that concatenates the given sequences, regardless of whether an error occurs in any of the
+        ///     sequences.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="sources">Source sequences.</param>
+        /// <returns>Sequence concatenating the elements of the given sequences, ignoring errors.</returns>
+        public static IEnumerable<TSource> OnErrorResumeNext<TSource>(this IEnumerable<IEnumerable<TSource>> sources)
+        {
+            if (sources == null)
+                throw new ArgumentNullException(nameof(sources));
+
+            return OnErrorResumeNext_(sources);
+        }
+
+        private static IEnumerable<TSource> OnErrorResumeNext_<TSource>(IEnumerable<IEnumerable<TSource>> sources)
+        {
+            foreach (var source in sources)
+            {
+                using (var innerEnumerator = source.GetEnumerator())
+                {
+                    while (true)
+                    {
+                        var value = default(TSource);
+                        try
+                        {
+                            if (!innerEnumerator.MoveNext())
+                                break;
+                            value = innerEnumerator.Current;
+                        }
+                        catch
+                        {
+                            break;
+                        }
+
+                        yield return value;
+                    }
+                }
+            }
+        }
+    }
+}

+ 188 - 0
Ix.NET/Source/System.Interactive/Publish.cs

@@ -0,0 +1,188 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Creates a buffer with a view over the source sequence, causing each enumerator to obtain access to the remainder of
+        ///     the sequence from the current index in the buffer.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <returns>
+        ///     Buffer enabling each enumerator to retrieve elements from the shared source sequence, starting from the index
+        ///     at the point of obtaining the enumerator.
+        /// </returns>
+        /// <example>
+        ///     var rng = Enumerable.Range(0, 10).Publish();
+        ///     var e1 = rng.GetEnumerator();    // e1 has a view on the source starting from element 0
+        ///     Assert.IsTrue(e1.MoveNext());
+        ///     Assert.AreEqual(0, e1.Current);
+        ///     Assert.IsTrue(e1.MoveNext());
+        ///     Assert.AreEqual(1, e1.Current);
+        ///     var e2 = rng.GetEnumerator();
+        ///     Assert.IsTrue(e2.MoveNext());    // e2 has a view on the source starting from element 2
+        ///     Assert.AreEqual(2, e2.Current);
+        ///     Assert.IsTrue(e1.MoveNext());    // e1 continues to enumerate over its view
+        ///     Assert.AreEqual(2, e1.Current);
+        /// </example>
+        public static IBuffer<TSource> Publish<TSource>(this IEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return new PublishedBuffer<TSource>(source.GetEnumerator());
+        }
+
+        /// <summary>
+        ///     Publishes the source sequence within a selector function where each enumerator can obtain a view over a tail of the
+        ///     source sequence.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="selector">Selector function with published access to the source sequence for each enumerator.</param>
+        /// <returns>Sequence resulting from applying the selector function to the published view over the source sequence.</returns>
+        public static IEnumerable<TResult> Publish<TSource, TResult>(this IEnumerable<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create(() => selector(source.Publish())
+                              .GetEnumerator());
+        }
+
+        private class PublishedBuffer<T> : IBuffer<T>
+        {
+            private RefCountList<T> _buffer;
+            private bool _disposed;
+            private Exception _error;
+            private IEnumerator<T> _source;
+            private bool _stopped;
+
+            public PublishedBuffer(IEnumerator<T> source)
+            {
+                _buffer = new RefCountList<T>(0);
+                _source = source;
+            }
+
+            public IEnumerator<T> GetEnumerator()
+            {
+                if (_disposed)
+                    throw new ObjectDisposedException("");
+
+                var i = default(int);
+                lock (_source)
+                {
+                    i = _buffer.Count;
+                    _buffer.ReaderCount++;
+                }
+
+                return GetEnumerator_(i);
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                if (_disposed)
+                    throw new ObjectDisposedException("");
+
+                return GetEnumerator();
+            }
+
+            public void Dispose()
+            {
+                lock (_source)
+                {
+                    if (!_disposed)
+                    {
+                        _source.Dispose();
+                        _source = null;
+
+                        _buffer.Clear();
+                        _buffer = null;
+                    }
+
+                    _disposed = true;
+                }
+            }
+
+            private IEnumerator<T> GetEnumerator_(int i)
+            {
+                try
+                {
+                    while (true)
+                    {
+                        if (_disposed)
+                            throw new ObjectDisposedException("");
+
+                        var hasValue = default(bool);
+                        var current = default(T);
+
+                        lock (_source)
+                        {
+                            if (i >= _buffer.Count)
+                            {
+                                if (!_stopped)
+                                {
+                                    try
+                                    {
+                                        hasValue = _source.MoveNext();
+                                        if (hasValue)
+                                            current = _source.Current;
+                                    }
+                                    catch (Exception ex)
+                                    {
+                                        _stopped = true;
+                                        _error = ex;
+
+                                        _source.Dispose();
+                                    }
+                                }
+
+                                if (_stopped)
+                                {
+                                    if (_error != null)
+                                        throw _error;
+                                    else
+                                        break;
+                                }
+
+                                if (hasValue)
+                                {
+                                    _buffer.Add(current);
+                                }
+                            }
+                            else
+                            {
+                                hasValue = true;
+                            }
+                        }
+
+                        if (hasValue)
+                            yield return _buffer[i];
+                        else
+                            break;
+
+                        i++;
+                    }
+                }
+                finally
+                {
+                    if (_buffer != null)
+                        _buffer.Done(i + 1);
+                }
+            }
+        }
+    }
+}

+ 83 - 0
Ix.NET/Source/System.Interactive/Repeat.cs

@@ -0,0 +1,83 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Generates a sequence by repeating the given value infinitely.
+        /// </summary>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="value">Value to repreat in the resulting sequence.</param>
+        /// <returns>Sequence repeating the given value infinitely.</returns>
+        public static IEnumerable<TResult> Repeat<TResult>(TResult value)
+        {
+            while (true)
+                yield return value;
+        }
+
+        /// <summary>
+        ///     Generates a sequence that contains one repeated value.
+        /// </summary>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="element">The value to be repeated.</param>
+        /// <param name="count">The number of times to repeat the value in the generated sequence.</param>
+        /// <returns>Sequence that contains a repeated value.</returns>
+        public static IEnumerable<TResult> Repeat<TResult>(TResult element, int count)
+        {
+            return Enumerable.Repeat(element, count);
+        }
+
+        /// <summary>
+        ///     Repeats and concatenates the source sequence infinitely.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <returns>Sequence obtained by concatenating the source sequence to itself infinitely.</returns>
+        public static IEnumerable<TSource> Repeat<TSource>(this IEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return Repeat_(source);
+        }
+
+        /// <summary>
+        ///     Repeats and concatenates the source sequence the given number of times.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="count">Number of times to repeat the source sequence.</param>
+        /// <returns>Sequence obtained by concatenating the source sequence to itself the specified number of times.</returns>
+        public static IEnumerable<TSource> Repeat<TSource>(this IEnumerable<TSource> source, int count)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count < 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            return Repeat_(source, count);
+        }
+
+        private static IEnumerable<TSource> Repeat_<TSource>(IEnumerable<TSource> source)
+        {
+            while (true)
+                foreach (var item in source)
+                    yield return item;
+        }
+
+        private static IEnumerable<TSource> Repeat_<TSource>(IEnumerable<TSource> source, int count)
+        {
+            for (var i = 0; i < count; i++)
+                foreach (var item in source)
+                    yield return item;
+        }
+    }
+}

+ 48 - 0
Ix.NET/Source/System.Interactive/Retry.cs

@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Creates a sequence that retries enumerating the source sequence as long as an error occurs.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <returns>Sequence concatenating the results of the source sequence as long as an error occurs.</returns>
+        public static IEnumerable<TSource> Retry<TSource>(this IEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return new[] {source}.Repeat()
+                                 .Catch();
+        }
+
+        /// <summary>
+        ///     Creates a sequence that retries enumerating the source sequence as long as an error occurs, with the specified
+        ///     maximum number of retries.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="retryCount">Maximum number of retries.</param>
+        /// <returns>Sequence concatenating the results of the source sequence as long as an error occurs.</returns>
+        public static IEnumerable<TSource> Retry<TSource>(this IEnumerable<TSource> source, int retryCount)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (retryCount < 0)
+                throw new ArgumentOutOfRangeException(nameof(retryCount));
+
+            return new[] {source}.Repeat(retryCount)
+                                 .Catch();
+        }
+    }
+}

+ 25 - 0
Ix.NET/Source/System.Interactive/Return.cs

@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Returns a sequence with a single element.
+        /// </summary>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="value">Single element of the resulting sequence.</param>
+        /// <returns>Sequence with a single element.</returns>
+        public static IEnumerable<TResult> Return<TResult>(TResult value)
+        {
+            yield return value;
+        }
+    }
+}

+ 86 - 0
Ix.NET/Source/System.Interactive/Scan.cs

@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Generates a sequence of accumulated values by scanning the source sequence and applying an accumulator function.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TAccumulate">Accumulation type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="seed">Accumulator seed value.</param>
+        /// <param name="accumulator">
+        ///     Accumulation function to apply to the current accumulation value and each element of the
+        ///     sequence.
+        /// </param>
+        /// <returns>Sequence with all intermediate accumulation values resulting from scanning the sequence.</returns>
+        public static IEnumerable<TAccumulate> Scan<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (accumulator == null)
+                throw new ArgumentNullException(nameof(accumulator));
+
+            return source.Scan_(seed, accumulator);
+        }
+
+        /// <summary>
+        ///     Generates a sequence of accumulated values by scanning the source sequence and applying an accumulator function.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="accumulator">
+        ///     Accumulation function to apply to the current accumulation value and each element of the
+        ///     sequence.
+        /// </param>
+        /// <returns>Sequence with all intermediate accumulation values resulting from scanning the sequence.</returns>
+        public static IEnumerable<TSource> Scan<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (accumulator == null)
+                throw new ArgumentNullException(nameof(accumulator));
+
+            return source.Scan_(accumulator);
+        }
+
+        private static IEnumerable<TAccumulate> Scan_<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
+        {
+            var acc = seed;
+
+            foreach (var item in source)
+            {
+                acc = accumulator(acc, item);
+                yield return acc;
+            }
+        }
+
+        private static IEnumerable<TSource> Scan_<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator)
+        {
+            var hasSeed = false;
+            var acc = default(TSource);
+
+            foreach (var item in source)
+            {
+                if (!hasSeed)
+                {
+                    hasSeed = true;
+                    acc = item;
+                    continue;
+                }
+
+                acc = accumulator(acc, item);
+                yield return acc;
+            }
+        }
+    }
+}

+ 32 - 0
Ix.NET/Source/System.Interactive/SelectMany.cs

@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Projects each element of a sequence to an given sequence and flattens the resulting sequences into one sequence.
+        /// </summary>
+        /// <typeparam name="TSource">First source sequence element type.</typeparam>
+        /// <typeparam name="TOther">Second source sequence element type.</typeparam>
+        /// <param name="source">A sequence of values to project.</param>
+        /// <param name="other">Inner sequence each source sequenec element is projected onto.</param>
+        /// <returns>Sequence flattening the sequences that result from projecting elements in the source sequence.</returns>
+        public static IEnumerable<TOther> SelectMany<TSource, TOther>(this IEnumerable<TSource> source, IEnumerable<TOther> other)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (other == null)
+                throw new ArgumentNullException(nameof(other));
+
+            return source.SelectMany(_ => other);
+        }
+    }
+}

+ 128 - 0
Ix.NET/Source/System.Interactive/Share.cs

@@ -0,0 +1,128 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Creates a buffer with a shared view over the source sequence, causing each enumerator to fetch the next element
+        ///     from the source sequence.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <returns>Buffer enabling each enumerator to retrieve elements from the shared source sequence.</returns>
+        /// <example>
+        ///     var rng = Enumerable.Range(0, 10).Share();
+        ///     var e1 = rng.GetEnumerator();    // Both e1 and e2 will consume elements from
+        ///     var e2 = rng.GetEnumerator();    // the source sequence.
+        ///     Assert.IsTrue(e1.MoveNext());
+        ///     Assert.AreEqual(0, e1.Current);
+        ///     Assert.IsTrue(e1.MoveNext());
+        ///     Assert.AreEqual(1, e1.Current);
+        ///     Assert.IsTrue(e2.MoveNext());    // e2 "steals" element 2
+        ///     Assert.AreEqual(2, e2.Current);
+        ///     Assert.IsTrue(e1.MoveNext());    // e1 can't see element 2
+        ///     Assert.AreEqual(3, e1.Current);
+        /// </example>
+        public static IBuffer<TSource> Share<TSource>(this IEnumerable<TSource> source)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return new SharedBuffer<TSource>(source.GetEnumerator());
+        }
+
+        /// <summary>
+        ///     Shares the source sequence within a selector function where each enumerator can fetch the next element from the
+        ///     source sequence.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <typeparam name="TResult">Result sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="selector">Selector function with shared access to the source sequence for each enumerator.</param>
+        /// <returns>Sequence resulting from applying the selector function to the shared view over the source sequence.</returns>
+        public static IEnumerable<TResult> Share<TSource, TResult>(this IEnumerable<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> selector)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (selector == null)
+                throw new ArgumentNullException(nameof(selector));
+
+            return Create(() => selector(source.Share())
+                              .GetEnumerator());
+        }
+
+        private class SharedBuffer<T> : IBuffer<T>
+        {
+            private bool _disposed;
+            private IEnumerator<T> _source;
+
+            public SharedBuffer(IEnumerator<T> source)
+            {
+                _source = source;
+            }
+
+            public IEnumerator<T> GetEnumerator()
+            {
+                if (_disposed)
+                    throw new ObjectDisposedException("");
+
+                return GetEnumerator_();
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                if (_disposed)
+                    throw new ObjectDisposedException("");
+
+                return GetEnumerator();
+            }
+
+            public void Dispose()
+            {
+                lock (_source)
+                {
+                    if (!_disposed)
+                    {
+                        _source.Dispose();
+                        _source = null;
+                    }
+
+                    _disposed = true;
+                }
+            }
+
+            private IEnumerator<T> GetEnumerator_()
+            {
+                while (true)
+                {
+                    if (_disposed)
+                        throw new ObjectDisposedException("");
+
+                    var hasValue = default(bool);
+                    var current = default(T);
+
+                    lock (_source)
+                    {
+                        hasValue = _source.MoveNext();
+                        if (hasValue)
+                            current = _source.Current;
+                    }
+
+                    if (hasValue)
+                        yield return current;
+                    else
+                        break;
+                }
+            }
+        }
+    }
+}

+ 46 - 0
Ix.NET/Source/System.Interactive/Skip.cs

@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Bypasses a specified number of contiguous elements from the end of the sequence and returns the remaining elements.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="count">
+        ///     The number of elements to skip from the end of the sequence before returning the remaining
+        ///     elements.
+        /// </param>
+        /// <returns>Sequence bypassing the specified number of elements counting from the end of the source sequence.</returns>
+        public static IEnumerable<TSource> SkipLast<TSource>(this IEnumerable<TSource> source, int count)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count < 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            return source.SkipLast_(count);
+        }
+
+        private static IEnumerable<TSource> SkipLast_<TSource>(this IEnumerable<TSource> source, int count)
+        {
+            var q = new Queue<TSource>();
+
+            foreach (var x in source)
+            {
+                q.Enqueue(x);
+                if (q.Count > count)
+                    yield return q.Dequeue();
+            }
+        }
+    }
+}

+ 38 - 0
Ix.NET/Source/System.Interactive/StartsWith.cs

@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Returns the source sequence prefixed with the specified value.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="values">Values to prefix the sequence with.</param>
+        /// <returns>Sequence starting with the specified prefix value, followed by the source sequence.</returns>
+        public static IEnumerable<TSource> StartWith<TSource>(this IEnumerable<TSource> source, params TSource[] values)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+
+            return source.StartWith_(values);
+        }
+
+        private static IEnumerable<TSource> StartWith_<TSource>(this IEnumerable<TSource> source, params TSource[] values)
+        {
+            foreach (var x in values)
+                yield return x;
+
+            foreach (var item in source)
+                yield return item;
+        }
+    }
+}

+ 51 - 0
Ix.NET/Source/System.Interactive/Take.cs

@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information. 
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+    public static partial class EnumerableEx
+    {
+        /// <summary>
+        ///     Returns a specified number of contiguous elements from the end of the sequence.
+        /// </summary>
+        /// <typeparam name="TSource">Source sequence element type.</typeparam>
+        /// <param name="source">Source sequence.</param>
+        /// <param name="count">The number of elements to take from the end of the sequence.</param>
+        /// <returns>Sequence with the specified number of elements counting from the end of the source sequence.</returns>
+        public static IEnumerable<TSource> TakeLast<TSource>(this IEnumerable<TSource> source, int count)
+        {
+            if (source == null)
+                throw new ArgumentNullException(nameof(source));
+            if (count < 0)
+                throw new ArgumentOutOfRangeException(nameof(count));
+
+            return source.TakeLast_(count);
+        }
+
+        private static IEnumerable<TSource> TakeLast_<TSource>(this IEnumerable<TSource> source, int count)
+        {
+            if (count == 0)
+            {
+                yield break;
+            }
+
+            var q = new Queue<TSource>(count);
+
+            foreach (var item in source)
+            {
+                if (q.Count >= count)
+                    q.Dequeue();
+                q.Enqueue(item);
+            }
+
+            while (q.Count > 0)
+                yield return q.Dequeue();
+        }
+    }
+}

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff