1

我想为某个接口创建一个代码合同,但是我很难相信它实际上是这样完成的。

[ContractClass(typeof(AsyncCacheProviderContract))]
public interface IAsyncCacheProvider {

    Task<bool> GetAsync<T>(string key, out T value);

}

[ContractClassFor(typeof(AsyncCacheProviderContract))]
internal abstract class AsyncCacheProviderContract : IAsyncCacheProvider {

    public Task<bool> GetAsync<T>(string key, out T value)
    {
        Contract.Requires(!String.IsNullOrEmpty(key));

        value = default(T);
        return Task.Factory.StartNew(() => false);
    }

}

合同应确保 1) 所有实现接口的类都要求参数不为 null 或为空,以及 2) 自动生成检查到构建中,例如类似于

public Task<bool> GetAsync<T>(string key, out T value) {
    if(String.IsNullOrEmpty(key))
        throw new ArgumentException //...
}

但是在这种特殊情况下,我感到很奇怪,我必须分配out参数并返回一个虚拟变量Task才能使编译器满意。有没有更直接的方法,例如使用属性?

4

1 回答 1

2

让我感到奇怪的是,我必须分配 out 参数并返回一个虚拟 Task 只是为了让编译器满意。

throw如果你是一个异常而不是return-ing 从方法中,你不必这样做。那么就不必构造返回值,也不必赋值给out参数:

[ContractClassFor(typeof(IAsyncCacheProvider))] // note: there's a small change here!
sealed class AsyncCacheProviderContract : IAsyncCacheProvider
{
    public Task<bool> GetAsync<T>(string key, out T value)
    {
        Contract.Requires(!String.IsNullOrEmpty(key));
        throw new NotSupportedException(); // makes the compiler happy, too
    }

    private AsyncCacheProviderContract() { } // optional safeguard:
}                                            // prevent instantiation (see below)

事实上,这在语义上比从方法返回更正确。为什么?因为没有人打算实际调用这些合约方法。他们从来不应该做任何有意义的工作,所以他们不需要返回任何有意义的值。您的合同类所需要的只是声明合同;实际工作在其他地方完成。

相关问题:
非空接口代码合同的实现 - default(T) vs throw NotImplementedException

于 2014-10-01T15:14:30.453 回答