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(…);
代码契约工具假设最后一个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(...)
。。。考虑到没有线程保护,我一开始也会对这些代码持谨慎态度。如果这是一个实例方法,我不会感到困扰,但访问静态(即全局)状态的静态方法通常应该是线程安全的。