为什么使用default(Type)时合约格式错误?

发布于 2024-09-16 04:20:43 字数 684 浏览 1 评论 0原文

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

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

失败并出现以下错误:

合同格式错误。在方法“.ObjectInvariant”中赋值后发现 Invariant。

如果代码像这样修改:

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

它可以很好地编译。

我的 default(Guid) 有什么问题吗?

When compiling code which uses code contracts, I have a very strange error I don't understand.

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

fails with the following error:

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

If the code is modified like this:

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

it compiles well.

What's wrong with my default(Guid)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蓝天白云 2024-09-23 04:20:43

为此生成的 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);

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

我会在代码契约论坛上报告此问题,它可能是漏洞。

The IL generated for this:

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

is:

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

Which corresponds to something like:

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

Code Contracts works directly on the IL, so it thinks you've written something like the second version. The rewriter is saying you're not allowed to assign to variables before the contracts, so it gives an error.

However, this is weird, because while this doesn't work:

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

this does, but it is clearly an "assignment before Invariant"!

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

I think they actually modified the checker to allow some assignments like this (for ease of use), but that they haven't allowed all cases... whether this is intended or not is beyond my knowledge.

I'd report this on the Code Contracts forum, it may be a bug.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文