使用默认(类型)时为什么合同格式错误?

时间:2010-08-29 23:23:04

标签: c# c#-4.0 default-value code-contracts

在编译使用代码契约的代码时,我有一个非常奇怪的错误,我不明白。

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

因以下错误而失败:

  

合同格式错误。在方法'< ProjectName> .ObjectInvariant'中分配后找到不变量。

如果代码修改如下:

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

它汇编得很好。

我的default(Guid)出了什么问题?

1 个答案:

答案 0 :(得分: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);

Code Contracts直接在IL上工作,所以它认为你写的是第二个版本。重写者说你不允许在合同之前分配变量,因此它会给出错误。

然而,这很奇怪,因为虽然这不起作用:

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

这样做,但显然是“在Invariant之前的任务”!

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

我认为他们实际上修改了检查器以允许这样的一些任务(为了便于使用),但是他们不允许所有情况......这是否有意为我所知。

我会在Code Contracts forum上报告,这可能是一个错误。