2014-10-01 34 views
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)實現該接口的所有類所需要的參數爲不爲零或爲空以及2)自動生成檢查到構建,例如類似

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

然而,在這種特殊情況下,它覺得很奇怪,我認爲我必須指定out參數以及返回一個空Task只是爲了讓編譯器高興。有沒有更直接的方式,例如使用屬性?

+1

小問題在你的代碼無關你的問題:在'ContractClassFor'屬性應該引用的接口,這樣'[ContractClassFor(typeof運算(IAsyncCacheProvider)) ]' – Keith 2014-10-01 14:47:29

回答

1

我感到很奇怪,我必須分配out參數以及返回一個虛擬任務只是爲了讓編譯器高興。

你沒有,如果你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) 

事實上,這是語義上比從方法返回更正確。爲什麼?因爲沒有人的意思是實際上是打電話這些合同的方法。他們從來不應該做任何有意義的工作,所以他們不需要返回任何有意義的值。所有你的合同類所要求的是它宣佈合同;實際的工作在其他地方完成。

相關問題:
Implementation of non-void interface Code Contracts - default(T) vs throw NotImplementedException