C#-代码协定-检测到的表达式语句已评估潜在的副作用

本文关键字:语句 评估 副作用 表达式 C#- 检测 代码 | 更新日期: 2023-09-27 18:20:51

我刚刚开始在C#中使用CodeContracts,可能需要一些帮助。我有一个类,它有一个键的静态列表,还有一个名为Remove()的静态方法,可以从该列表中删除一个键。

现在,我从合同发布条件中了解到,作为类的程序员,我保证当前的公共方法会做一些特定的事情,在这种情况下:删除列表中的元素。

这是我写的:

    private static List<Keys> m_usedKeys; // private list of keys
    public static void Remove(Keys _key)
    {
        m_usedKeys.Remove(_key);
        Contract.Ensures(!m_usedKeys.Any(x => x == _key));
    }

我在这里试图"确保"的是,Remove()方法从列表中删除了real的密钥(是的,这可能是一个微不足道的例子,但我在那里得到了错误。)

当我写Contract.Ensures()行时,VS2010给了我以下错误:

Error   3   Detected expression statement evaluated for potential side-effect in contracts of method 'LibJungleTimer.KeyBind.Remove(System.Windows.Forms.Keys)'. (Did you mean to put the expression into a Requires, Ensures, or Invariant call?)  C:'Users'Joel'Documents'Programmation'JT'JungleTimer'LibJungleTimer'KeyBind.cs  51

我认为这个错误说明表达式m_usedKeys.remove(_key);有潜在的副作用。事实上,它有一个副作用,它从列表中删除了一个键!

如果我试着写这样的东西:

Contract.Assert(!m_usedKeys.Any(x => x == _key));

它编译得很好。我的问题是我做错了什么?难道CodeContracts不应该这样用来确保后期条件吗?

编辑:是的,我的意思是!m_usedKeys.Any(…);

C#-代码协定-检测到的表达式语句已评估潜在的副作用

代码契约工具假设最后一个Contract.Ensures/Contract.Requires之前的任何内容都是契约的一部分。。。所以它认为您对Remove的调用是合同的一部分,而不是实现的一部分。您必须反转代码,以便在实现之前所有合同代码。

public static void Remove(Keys _key)
{
    Contract.Ensures(m_usedKeys.Any(x => x == _key));        
    m_usedKeys.Remove(_key);
}

顺便说一下,我怀疑你想要!m_usedKeys.Any(...)。。。考虑到没有线程保护,我一开始也会对这些代码持谨慎态度。如果这是一个实例方法,我不会感到困扰,但访问静态(即全局)状态的静态方法通常应该是线程安全的。