Oren Novotny пре 9 година
родитељ
комит
3be42ecd5d

+ 4 - 0
Ix.NET/Source/System.Interactive.Async/AsyncIterator.cs

@@ -73,6 +73,10 @@ namespace System.Linq
 
             public async Task<bool> MoveNext(CancellationToken cancellationToken)
             {
+                // Note: MoveNext *must* be implemented as an async method to ensure
+                // that any exceptions thrown from the MoveNextCore call are handled 
+                // by the try/catch, whether they're sync or async
+
                 if (state == AsyncIteratorState.Disposed)
                 {
                     return false;

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

@@ -110,6 +110,9 @@ namespace System.Linq
                             }
                             catch (TException ex)
                             {
+                                // Note: Ideally we'd dipose of the previous enumerator before
+                                // invoking the handler, but we use this order to preserve
+                                // current behavior
                                 var err = handler(ex)
                                     .GetEnumerator();
                                 enumerator?.Dispose();

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

@@ -74,6 +74,9 @@ namespace System.Linq
                         else
                         {
                             current = defaultValue;
+                            enumerator.Dispose();
+                            enumerator = null;
+
                             state = AsyncIteratorState.Disposed; 
                         }
                         return true;

+ 21 - 2
Ix.NET/Source/System.Interactive.Async/Distinct.cs

@@ -132,8 +132,27 @@ namespace System.Linq
 
             public async Task<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken)
             {
-                return onlyIfCheap ? -1 : (await FillSet(cancellationToken)
-                                               .ConfigureAwait(false)).Count;
+                if (onlyIfCheap)
+                {
+                    return -1;
+                }
+
+                var count = 0;
+                var s = new Set<TKey>(comparer);
+                using (var enu = source.GetEnumerator())
+                {
+                    while (await enu.MoveNext(cancellationToken)
+                                    .ConfigureAwait(false))
+                    {
+                        var item = enu.Current;
+                        if (s.Add(keySelector(item)))
+                        {
+                            count++;
+                        }
+                    }
+                }
+
+                return count;
             }
 
             public override AsyncIterator<TSource> Clone()

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

@@ -125,9 +125,9 @@ namespace System.Linq
             {
                 var array = await second.ToArray(cancellationToken)
                                         .ConfigureAwait(false);
-                for (var i = 0; i < array.Length; i++)
+                foreach (var t in array)
                 {
-                    set.Add(array[i]);
+                    set.Add(t);
                 }
             }
         }

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

@@ -212,7 +212,7 @@ namespace System.Linq
 
             public Task<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken)
             {
-                return Task.FromResult(source.Count());
+                return Task.FromResult(source.Count);
             }
 
             IEnumerator<T> IEnumerable<T>.GetEnumerator() => source.GetEnumerator();
@@ -299,7 +299,7 @@ namespace System.Linq
             }
             public Task<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken)
             {
-                return Task.FromResult(source.Count());
+                return Task.FromResult(source.Count);
             }
             IEnumerator<T> IEnumerable<T>.GetEnumerator() => source.GetEnumerator();
             IEnumerator IEnumerable.GetEnumerator() => source.GetEnumerator();