了解接口的代码契约

时间:2014-10-01 11:19:17

标签: c# validation code-contracts codeguard

我想为某个界面创建一个代码契约,但是我很难相信它实际上是这样做的。

[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)实现接口的所有类都要求参数 key 不为null或为空以及2)自动生成对构建的检查,例如:类似于

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

然而在这种特殊情况下,我感到很奇怪,我必须分配out参数以及返回一个虚拟Task只是为了让编译器满意。有没有更简单的方法,例如使用属性?

1 个答案:

答案 0 :(得分:2)

  

我感到很奇怪,我必须分配out参数以及返回一个伪任务,以使编译器满意。

如果您从方法中throw例外而不是return,则不必如此。那么你不必构造一个返回值,也不需要分配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)

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

  

相关问题:
  Implementation of non-void interface Code Contracts - default(T) vs throw NotImplementedException