之前是否发现了在C#中使用async / await?

在关于async / await的stackoverflow之前的一个问题之后,在我看来,await比营销建议更强大和更通用。 它似乎是构建计算表达式的一般方法,就像在F#中一样。 因此,经过一番努力,我想出了一些成功执行的代码,如下所示。

using FluentAssertions; using System.Collections.Generic; namespace EnumerableViaAwait.Specs { [global::Microsoft.VisualStudio.TestTools.UnitTesting.TestClass] public class MyTestClass { public IEnumerable Numbers() { return EnumeratorMonad.Build(async Yield => { await Yield(11); await Yield(22); await Yield(33); }); } [Microsoft.VisualStudio.TestTools.UnitTesting.TestMethod] public void TestEnum() { var v = Numbers(); var e = v.GetEnumerator(); int[] expected = { 11, 22, 33 }; Numbers().Should().ContainInOrder(expected); } } } 

现在仔细注意这里发生了什么。 我构建react native观察。 我正在构建一个IEnumerable。 它严格来说是拉动系统。 我很高兴写作。

  foreach item in Numbers(){ Console.WriteLine(item); } 

它会打印出来

  11 22 33 

这非常有趣,因为系统不是严格异步的,但我滥用了await框架和“等待任何东西”的能力,如此处所述。 http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115642.aspx。 问题是。

  1. 这种滥用await / async会走多远?
  2. 这种模式是否与F#计算表达式一样强大
  3. 传统的IEnumerator / Yield模式只是语法糖,它完全评估这种模式

实现该模式的代码如下

  using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; namespace EnumerableViaAwait { public class EnumeratorMonad : IEnumerable, IEnumerator { public class Yield { private EnumeratorMonad _Monad; public Yield(EnumeratorMonad monad) { _Monad = monad; } public YieldAwaiter GetAwaiter() { return new YieldAwaiter(_Monad); } } public class YieldAwaiter : INotifyCompletion { EnumeratorMonad _Monad; public YieldAwaiter(EnumeratorMonad monad) { _Monad = monad; } public bool IsCompleted { get { return _Monad.IsCompleted(); } } public void GetResult() { } public void OnCompleted(Action continuation) { _Monad.Next = continuation; } } private bool Completed { get; set; } public EnumeratorMonad() { Completed = false; } public bool IsCompleted() { return Completed; } public void Build(Func<Func, Task> action) { Func yielder = (T value) => { _Current = value; return new Yield(this); }; Next = async () => { await action(yielder); Completed = true; }; } private T _Current; public T Current { get { return _Current; } } public void Dispose() { } object System.Collections.IEnumerator.Current { get { return _Current; } } Action Next; public bool MoveNext() { if (!Completed ) { Next(); } return !Completed; } public void Reset() { throw new NotImplementedException(); } IEnumerator IEnumerable.GetEnumerator() { return this; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this; } } public class EnumeratorMonad{ public static EnumeratorMonad Build(Func<Func<T, EnumeratorMonad.Yield>, Task> action) { var monad = new EnumeratorMonad(); monad.Build(action); return monad; } } 

}

yield returnawait / async只是协同程序的不同专用forms。 你已经表明你可以(基本上)使用await / async实现yield return ,而且我不会惊讶地发现它可能yield return 。 我确信它们的实现方式非常相似。

当然,在实践中,我不会使用await / async进行迭代,因为yield return更简单,更清晰。

所以,

  1. 您可以根据需要接受这种“滥用”。
  2. 不熟悉F#来回答。
  3. 不,但是IIRC的function或多或少都以相同的方式实现。