2010-08-29 84 views
9

編譯使用代碼合同的代碼時,我有一個很奇怪的錯誤,我不明白。爲什麼使用默認(類型)時合同格式錯誤?

[ContractInvariantMethod] 
private void ObjectInvariant() 
{ 
    Contract.Invariant(
     this.isSubsidiary || 
     this.parentCompanyId == default(Guid)); 
} 

失敗,出現以下錯誤:

Malformed contract. Found Invariant after assignment in method '<ProjectName>.ObjectInvariant'.

如果代碼被修改如下:

[ContractInvariantMethod] 
private void ObjectInvariant() 
{ 
    Contract.Invariant(
     this.isSubsidiary || 
     this.parentCompanyId == Guid.Empty); 
     // Noticed the Guid.Empty instead of default(Guid)? 
} 

它編譯良好。我的default(Guid)有什麼問題?

+0

據我所知:public static readonly Guid Empty;和默認(Guid)或新的Guid()是相同的東西 我不知道它爲什麼不在這裏運作。 – abhishek 2010-08-29 23:38:26

+0

我也遇到過。奇怪的是默認(int)不具有相同的效果。 – 2011-07-22 10:06:29

+0

@Can Gencer:我認爲這是預期的,如果你讀Porges的答案。對於'default(Guid)',IL對應於'Guid something = new Guid()',所以有一個對方法(構造函數)的調用。相反,'default(int)'不會對應'int something = new int()',這是沒有意義的。這就是爲什麼'int'的情況,編譯器不會抱怨。 – 2011-07-22 10:23:10

回答

6

的IL此產生:

Console.WriteLine("{0}, {1}", default(Guid), Guid.Empty); 

是:

.locals init (
     [0] valuetype [mscorlib]System.Guid CS$0$0000) 
    L_0000: nop 
    L_0001: ldstr "{0}, {1}" 
    L_0006: ldloca.s CS$0$0000 
    L_0008: initobj [mscorlib]System.Guid 
    L_000e: ldloc.0 
    L_000f: box [mscorlib]System.Guid 
    L_0014: ldsfld valuetype [mscorlib]System.Guid [mscorlib]System.Guid::Empty 
    L_0019: box [mscorlib]System.Guid 
    L_001e: call void [mscorlib]System.Console::WriteLine(string, object, object) 

對應於這樣的:

Guid CS$0$0000 = new Guid(); 
Console.WriteLine("{0}, {1}", CS$0$0000, Guid.Empty); 

代碼契約直接作用於IL,所以它認爲你寫了類似第二個版本的東西。重寫者說你不允許在契約之前分配變量,所以它會給出錯誤。

然而,這是奇怪的,因爲雖然這不起作用:

var x = new Guid(); 
Contract.Invariant(
    this.isSubsidiary || 
    this.parentCompanyId == x); 

這樣做,但它顯然是一個「不變之前分配」!

var x = Guid.Empty; 
Contract.Invariant(
    this.isSubsidiary || 
    this.parentCompanyId == x); 

我認爲他們實際上修改了檢查,使一些像這樣的分配(易用性),但他們沒有讓所有的情況下......這是否是有意或無意超出了我的知識。

我會在Code Contracts forum上報告這個,它可能是一個錯誤。

相關問題