bra*_*ing 5 c# monads asynchronous async-await visual-studio-2012
在关于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<int> Numbers()
{
return EnumeratorMonad.Build<int>(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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在仔细注意这里发生了什么.我不构建反应性观察.我正在构建一个IEnumerable.它严格来说是拉动系统.我很乐意写作.
foreach item in Numbers(){
Console.WriteLine(item);
}
Run Code Online (Sandbox Code Playgroud)
它会打印出来
11
22
33
Run Code Online (Sandbox Code Playgroud)
这非常有趣,因为系统不是严格异步的,但我滥用了await框架和"等待任何东西"的能力,如此处所述.http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115642.aspx. 问题是.
实现该模式的代码如下
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<T> : IEnumerable<T>, IEnumerator<T>
{
public class Yield
{
private EnumeratorMonad<T> _Monad;
public Yield(EnumeratorMonad<T> monad)
{
_Monad = monad;
}
public YieldAwaiter GetAwaiter()
{
return new YieldAwaiter(_Monad);
}
}
public class YieldAwaiter : INotifyCompletion
{
EnumeratorMonad<T> _Monad;
public YieldAwaiter(EnumeratorMonad<T> 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<T, Yield>, Task> action)
{
Func<T, Yield> 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<T> IEnumerable<T>.GetEnumerator()
{
return this;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this;
}
}
public class EnumeratorMonad{
public static EnumeratorMonad<T> Build<T>(Func<Func<T, EnumeratorMonad<T>.Yield>, Task> action)
{
var monad = new EnumeratorMonad<T>();
monad.Build(action);
return monad;
}
}
Run Code Online (Sandbox Code Playgroud)
}
yield return和await/async只是协程的不同专门形式。您已经证明您可以(本质上)yield return使用await/实现async,并且我不会惊讶地发现反过来也是可能的。我确信它们是以非常相似的方式实现的。
当然,在实践中,我不会使用await/async进行迭代,因为yield return它更简单、更清晰。
所以,
| 归档时间: |
|
| 查看次数: |
1238 次 |
| 最近记录: |