【问题标题】:Contracts - How to Require collection contains no nulls合同 - 如何要求集合不包含空值
【发布时间】:2015-03-11 19:57:11
【问题描述】:

我的类上有一个返回 List<MyType> 的内部属性,我想使用静态检查来帮助我不在我的程序集中做任何愚蠢的事情,并可能向该集合添加一个 null。

我在属性上的 foreach 的循环变量上收到此静态警告。

警告 149 CodeContracts:可能在 null 上调用方法 参考“myLoopVariable”。你期待吗 System.Collections.Generic.List`1+Enumerator.get_Current 返回非空?

过去我的集合包含空值从来没有遇到过任何问题,但是当编译器和我不同意时,这是对的,我错了,因此我希望警告消失。这只是我之前从未想过的事情,果然MyClass.MyListProperty.Add(null)可以做到,所以确实有效。

我不能在使用循环变量的地方做Requires,因为我得到了错误:

try 块中的合约部分

它让我(没有任何错误)在方法中添加Requires

Contract.Requires<ArgumentException>(Contract.ForAll<MyClass>(MyClassInstance.MyListProperty, x => x != null))

但是,这并没有导致原始警告消失,并且还导致了附加警告:

警告 149 CodeContracts:需要未经证实: Contract.ForAll(MyClassInstance.MyListProperty, x => x != 空)

我想知道是否有一种方法可以将该逻辑放在一个位置,靠近属性定义本身。

代码合约提供什么机制来实现这一点?

编辑:

我开始认为我将不得不再次将MyListProperty 设为私有,并限制对其的访问。否则,有人(我)可以添加null 到它! (但存在的挑战是,如何允许“受信任的”访问者进行枚举?哦,天哪!)

【问题讨论】:

  • 我假设“循环变量”不在方法范围内?
  • @PeterRitchie,它在循环声明中声明。它可以在方法级别声明。你的想法是什么?
  • 据我所知,Requires 位于方法的顶部...
  • ...但是,我认为这并不能真正解决您想要做的事情。
  • @toddmo - 我在下面提供了 3 种可能的解决方案,每一种都可以正常工作。

标签: c# code-contracts


【解决方案1】:

Assume 会收到消息,但我不确定这是否会导致性能问题,而且这似乎是多余的。不幸的是,如果不使用 Contract.Assume,我无法摆脱静态检查器消息。

// at the beginning of your method
Contract.Requires(MyCollection != null && Contract.ForAll(MyCollection, x => x != null));
// other code
foreach(var item in MyCollection)
{
   Contract.Assume(item != null);
   // call method on item which can create a message from the static checker if the assume is not included
}

【讨论】:

  • Contract.ForAll,而不是Enumerable.All。前者至少有很小的机会与静态检查器一起工作,后者绝对不会。不过,我并不乐观,即使有这种变化也足够了。
  • 1.我更新了我的问题,以显示我尝试这样做时发生了什么。我还不知道“需要未经证实”是什么意思。我执行错了吗? 2. 如果我在属性正文中使用Ensures,会关闭警告但仍允许空值吗? 3. 与#2 相同的问题。
  • @toddmo 我在 Ensures 上错了,这是因为如果您使用支持字段,它的可见性低于属性 getter 本身,因此无法正常工作。我之前错过了你想要完成的事情,我正在玩弄它,并会尝试看看我是否能找到一些东西,除非有人打败我。
  • 祝你好运,神速,再次感谢
  • @toddmo - 我更新了我的答案,但我个人不喜欢生成的代码。它确实摆脱了静态检查器创建的消息。
猜你喜欢
  • 1970-01-01
  • 2012-02-17
  • 2015-03-15
  • 1970-01-01
  • 2011-08-11
  • 2012-11-30
  • 2011-07-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多