9

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

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

失败并出现以下错误:

格式错误的合同。在方法 '<ProjectName>.ObjectInvariant' 中分配后发现 Invariant。

如果代码被这样修改:

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

它编译得很好。

我的怎么了default(Guid)

4

1 回答 1

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

确实如此,但它显然是“不变量之前的赋值”!

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

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

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

于 2010-08-30T01:05:01.963 回答