C# - 代码合约 - 检测到的表达式语句评估潜在的副作用
我刚刚开始在 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() 方法会从列表中真正删除密钥(是的,这可能是一个简单的例子,但我在那里得到了错误。)
当我编写 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(...);
I have just started using CodeContracts with C#, and I might need some help. I have a class with a static list of keys, and I have a static method called Remove() that removes a key from that list.
Now what I understand from the contracts post conditions is that as the programmer of the class, I guarantee that the current public method does something specific, in this case : removing the element of the list.
Here's what I've written:
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));
}
What I'm trying to "Ensure" here, is that the Remove() method removes the key for real from the list (Yes this might be a trivial example, but I get the error there.)
when I write the Contract.Ensures() line, VS2010 gives me the following error :
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
I think this error says that the expression m_usedKeys.remove(_key);
has a potential side-effect. In fact, it has a side-effect, it removes a key from the list!
If I try to write something like this instead :
Contract.Assert(!m_usedKeys.Any(x => x == _key));
well it compiles fine. My question is what am I doing wrong? Shouldn't CodeContracts be used like that to ensure a post condition?
EDIT: Yes I indeed meant !m_usedKeys.Any(...);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
代码契约工具假定最后一个
Contract.Ensures
/Contract.Requires
之前的任何内容都是契约的一部分...因此它认为您对Remove< 的调用/code> 是合同的一部分,而不是实施的一部分。您必须反转您的代码,以便所有合约代码都在实现之前。
顺便说一句,我怀疑您想要
!m_usedKeys.Any(...)
...而且我也会对这段代码保持警惕,因为您没有线程保护地方。如果这是一个实例方法,我不会担心,但访问静态(即全局)状态的静态方法通常应该是线程安全的。The Code Contracts tool assumes that anything before the last
Contract.Ensures
/Contract.Requires
is part of the contract... so it thinks your call toRemove
is part of the contract, not part of the implementation. You have to reverse your code, so that all the contract code is before the implementation.I suspect you want
!m_usedKeys.Any(...)
by the way... and I'd also be wary of this code to start with, given that you've got no threading protection in place. It wouldn't bother me if this were an instance method, but static methods accessing static (i.e. global) state should generally be thread-safe.