2010-08-29 11 views
9

Khi biên dịch mã sử dụng hợp đồng mã, tôi có một lỗi rất lạ mà tôi không hiểu.Tại sao hợp đồng không đúng định dạng khi sử dụng mặc định (Loại)?

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

không thành công với các lỗi sau:

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

Nếu mã được sửa đổi như sau:

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

nó biên dịch tốt.

Có gì sai với default(Guid) của tôi?

+0

Theo như tôi biết: public static readonly Guid Empty; và mặc định (Hướng dẫn) hoặc Hướng dẫn mới() giống nhau Tôi không biết tại sao nó không hoạt động ở đây. – abhishek

+0

Tôi cũng gặp phải điều này. Curiously mặc định (int) không có tác dụng tương tự. –

+0

@Can Gencer: Tôi nghĩ rằng điều này được mong đợi nếu bạn đọc câu trả lời của Porges. Đối với 'default (Guid)', IL tương ứng với 'Guid something = new Guid()', vì vậy có một lời gọi đến phương thức (constructor). Thay vào đó, 'default (int)' sẽ không tương ứng với 'int something = new int()', nó không có ý nghĩa gì cả. Đó là lý do tại sao trong trường hợp 'int', trình biên dịch không phàn nàn. –

Trả lời

6

Các IL tạo ra cho việc này:

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

là:

.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) 

nào tương ứng với cái gì đó như:

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

Hợp đồng Mã làm việc trực tiếp trên IL, vì vậy nó nghĩ bạn đã viết một cái gì đó giống như phiên bản thứ hai. Người viết lại nói rằng bạn không được phép gán cho các biến trước các hợp đồng, do đó, nó đưa ra một lỗi.

Tuy nhiên, đây là kỳ lạ, bởi vì trong khi điều này không làm việc:

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

này không, nhưng rõ ràng là một "nhiệm vụ trước khi bất biến"!

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

Tôi nghĩ họ thực sự biến đổi chức năng kiểm tra để cho phép một số bài tập như thế này (để dễ sử dụng), nhưng họ đã không được phép mọi trường hợp ... cho dù đây là dự định hay không là ngoài kiến ​​thức của tôi.

Tôi muốn báo cáo điều này trên số Code Contracts forum, đây có thể là lỗi.