浏览代码

Address feedback round 1

Dávid Karnok 7 年之前
父节点
当前提交
eb5cbb5497

+ 16 - 5
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Never.cs

@@ -20,7 +20,7 @@ namespace System.Linq
         {
             internal static readonly NeverAsyncEnumerable<TValue> Instance = new NeverAsyncEnumerable<TValue>();
 
-            public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken = default)
+            public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken)
             {
                 return new NeverAsyncEnumerator(cancellationToken);
             }
@@ -31,6 +31,12 @@ namespace System.Linq
 
                 private readonly CancellationToken _token;
 
+                private CancellationTokenRegistration _registration;
+
+                private bool _once;
+
+                private TaskCompletionSource<bool> _task;
+
                 public NeverAsyncEnumerator(CancellationToken token)
                 {
                     _token = token;
@@ -38,16 +44,21 @@ namespace System.Linq
 
                 public ValueTask DisposeAsync()
                 {
+                    _registration.Dispose();
+                    _task = null;
                     return TaskExt.CompletedTask;
                 }
 
                 public ValueTask<bool> MoveNextAsync()
                 {
-                    return new ValueTask<bool>(Task.Run(async () =>
+                    if (_once)
                     {
-                        await Task.Delay(Threading.Timeout.Infinite, _token);
-                        return false;
-                    }, _token));
+                        return TaskExt.False;
+                    }
+                    _once = true;
+                    _task = new TaskCompletionSource<bool>();
+                    _registration = _token.Register(state => ((NeverAsyncEnumerator)state)._task.SetCanceled(), this);
+                    return new ValueTask<bool>(_task.Task);
                 }
             }
         }

+ 1 - 1
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Return.cs

@@ -26,7 +26,7 @@ namespace System.Linq
                 _value = value;
             }
 
-            public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken = default)
+            public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken)
             {
                 return new ReturnEnumerator(_value);
             }

+ 25 - 15
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Throw.cs

@@ -31,34 +31,44 @@ namespace System.Linq
             );
         }
 
-        private sealed class ThrowEnumerable<TValue> : IAsyncEnumerable<TValue>, IAsyncEnumerator<TValue>
+        private sealed class ThrowEnumerable<TValue> : IAsyncEnumerable<TValue>
         {
             private readonly ValueTask<bool> _moveNextThrows;
 
-            public TValue Current => default;
-
             public ThrowEnumerable(ValueTask<bool> moveNextThrows)
             {
                 _moveNextThrows = moveNextThrows;
             }
 
-            public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken = default)
+            public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken)
             {
-                return this;
+                return new ThrowEnumerator(_moveNextThrows);
             }
 
-            public ValueTask DisposeAsync()
+            private sealed class ThrowEnumerator : IAsyncEnumerator<TValue>
             {
-                return TaskExt.CompletedTask;
-            }
+                private ValueTask<bool> _moveNextThrows;
+
+                public ThrowEnumerator(ValueTask<bool> moveNextThrows)
+                {
+                    _moveNextThrows = moveNextThrows;
+                }
+
+                public TValue Current => default;
+
+                public ValueTask DisposeAsync()
+                {
+                    _moveNextThrows = TaskExt.False;
+                    return TaskExt.CompletedTask;
+                }
+
+                public ValueTask<bool> MoveNextAsync()
+                {
+                    var result = _moveNextThrows;
+                    _moveNextThrows = TaskExt.False;
+                    return result;
+                }
 
-            public ValueTask<bool> MoveNextAsync()
-            {
-                // May we let this fail over and over?
-                // If so, the class doesn't need extra state
-                // and thus can be reused without creating an
-                // async enumerator
-                return _moveNextThrows;
             }
         }
     }