【问题标题】:Code Contracts warning about possibly failing 'Assume' call代码合同警告可能失败的“假设”调用
【发布时间】:2011-03-05 00:08:38
【问题描述】:

在我的一个班级中,我有一个 ExpandoObject 类型的私有字段。该字段在构造函数中初始化(this.expected = new ExpandoObject()),所以我相信它永远不会是null

因此,在这个类的一个方法中,我可以安全地添加

Contract.Assumes(this.expected != null)

在使用this.expected 之前,代码契约不必担心可能调用空对象。但是,我收到一条警告,而不是警告可能调用空引用的方法

对方法“Assume”的动态调度调用可能在运行时失败,因为一个或多个适用的重载是条件方法

方法签名和前几行代码如下所示:

protected void Expect(object values)
{
    Contract.Requires<ArgumentNullException>(values != null);

    Contract.Assume(this.expected != null);
    var exp = (ICollection<KeyValuePair<string, object>>)this.expected;

在第三行,我收到警告

CodeContracts:可能在空引用“OddEnds.Testing.TestBase.o_SiteContainer0.p_Site3.Target”上调用方法

我假设空引用的奇怪签名是因为exp 是一个动态对象。

我该如何解决这些问题?

【问题讨论】:

  • 你谈到了这个领域,扩展的,预期的。似乎它们都是同一个领域,但不可能进行逆向工程。检查您的问题是否准确。
  • 抱歉 - 我有点太快了......正如你所假设的,它们都指的是同一个字段,现在称为 expected,就像在我的代码中一样。跨度>
  • 想知道如果将 Assume 替换为 Assert 是否会存在相同的警告?

标签: c# code-contracts


【解决方案1】:

我认为解决您的问题的最佳方法是声明 expected 永远不会为 null 作为类的不变量:

class TheClass {

    ExpandoObject expected;

    ...

    [ContractInvariantMethod]
    void Invariants()
    {
        Contract.Invariant(this.expected != null);
    }

    ...

}

当您执行此操作时,静态检查器将在构造函数的末尾检查 expected 是否不为空,然后它会知道 expected 在任何其他方法的开头绝不为空。

【讨论】:

  • 这很性感! =) 我可能会在这里和其他一些情况下使用这个,但我有一个后续问题:不变合约是一次性的吗?即,我可以在Dispose 方法中实现IDisposable 而不破坏blaha != null 合同吗?
  • 只要不将blaha设置为null就可以了。 :) (实际上,您可以实现一个具有== 的反常类型,这取决于它是否被处置,这可能会破坏它......但无论如何这都很讨厌。)
  • 但是如果我在Dispose 方法中有blaha = null; 它会中断吗?
  • 是的。在每个方法结束时检查不变量。您可以尝试将Contract.Invariant(disposed || blaha != null) 与标志变量disposed 一起使用,但我认为您必须在您的方法中添加前提条件Contract.Requires(!disposed)。是否有任何特殊原因需要将blaha 设置为null
  • 不,我只是想知道 =) 不幸的是,这不是根本原因 - 现在,CC 抱怨无法验证不变量...
【解决方案2】:

我认为以下代码更改将使编译器满意(如果你确定在这个演员阵容中,但为什么要使用 expandoobject ......无论如何)

ICollection<KeyValuePair<string, object>> col = this.expected as ICollection<KeyValuePair<string, object>>;
Contract.Assume(col != null);

【讨论】:

  • 我以前也有过,但为了让编译器满意,我把它改成了显式转换:P
猜你喜欢
  • 2012-09-12
  • 2018-07-24
  • 1970-01-01
  • 1970-01-01
  • 2011-06-13
  • 2021-07-07
  • 2015-07-29
  • 2015-01-21
  • 1970-01-01
相关资源
最近更新 更多