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

Ars*_*nko 9 c# default-value code-contracts c#-4.0

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

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

失败,出现以下错误:

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

如果代码修改如下:

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

它汇编得很好.

我有什么问题default(Guid)

por*_*ges 6

为此生成的IL:

Console.WriteLine("{0}, {1}", default(Guid), Guid.Empty);
Run Code Online (Sandbox Code Playgroud)

是:

    .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)
Run Code Online (Sandbox Code Playgroud)

这对应于以下内容:

Guid CS$0$0000 = new Guid();
Console.WriteLine("{0}, {1}", CS$0$0000, Guid.Empty);
Run Code Online (Sandbox Code Playgroud)

Code Contracts直接在IL上工作,因此它认为你已经编写了类似第二版的东西.重写者说你不允许在合同之前分配变量,所以它给出了一个错误.

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

var x = new Guid();
Contract.Invariant(
    this.isSubsidiary ||
    this.parentCompanyId == x);
Run Code Online (Sandbox Code Playgroud)

这样做,但它显然是"Invariant之前的任务"!

var x = Guid.Empty;
Contract.Invariant(
    this.isSubsidiary ||
    this.parentCompanyId == x);
Run Code Online (Sandbox Code Playgroud)

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

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