正如其他人所做的那样,我已经向 Async 团队指出了这一点。目前,Contracts 和 Async (几乎)是互斥的。所以,至少微软的一些人意识到了这个问题,但我不知道他们打算做什么。
我不建议将异步方法编写为同步方法的包装器。事实上,我倾向于做相反的事情。
先决条件可以工作。我最近没试过;您可能需要一个包含先决条件的异步方法的小包装器。
后置条件几乎被打破了。
断言和假设确实可以正常工作,但是静态检查器确实受到限制,因为后置条件被破坏了。
不变量在异步世界中没有多大意义,可变状态往往会阻碍。(异步轻轻地将您从 OOP 推向函数式风格)。
希望在 VS vNext 中,Contracts 将使用一种异步感知的后置条件进行更新,这也将使静态检查器能够更好地处理异步方法中的断言。
同时,您可以通过编写一个假设来拥有一个假装后置条件:
// Synchronous version for comparison.
public static string Reverse(string s)
{
Contract.Requires(s != null);
Contract.Ensures(Contract.Result<string>() != null);
return ...;
}
// First wrapper takes care of preconditions (synchronously).
public static Task<string> ReverseAsync(string s)
{
Contract.Requires(s != null);
return ReverseWithPostconditionAsync(s);
}
// Second wrapper takes care of postconditions (asynchronously).
private static async Task<string> ReverseWithPostconditionAsync(string s)
{
var result = await ReverseImplAsync(s);
// Check our "postcondition"
Contract.Assume(result != null);
return result;
}
private static async Task<string> ReverseImplAsync(string s)
{
return ...;
}
代码契约的某些用法是不可能的——例如,在接口或基类的异步成员上指定后置条件。
就我个人而言,我刚刚在我的异步代码中完全避免了合同,希望微软能在几个月内修复它。