合同 - 如何要求集合不包含空值

Contracts - How to Require collection contains no nulls

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

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

Warning 149 CodeContracts: Possibly calling a method on a null reference 'myLoopVariable'. Do you expect that System.Collections.Generic.List`1+Enumerator.get_Current returns non-null?

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

我无法在使用循环变量的地方执行 Requires,因为出现错误:

Contract section within a try block

它让我(没有任何错误)向方法添加一个 Requires

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

但是,这并没有导致原来的警告消失,而且还产生了一个额外的警告:

Warning 149 CodeContracts: requires unproven: Contract.ForAll(MyClassInstance.MyListProperty, x => x != null)

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

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

编辑:

我开始认为我将不得不再次将 MyListProperty 设为私有,并限制对它的访问。否则,有人(我)可以在其中添加 null! (但挑战是,如何允许 "trusted" 访问者枚举?天啊!)

假设会收到消息,但我不确定这是否会导致性能问题,而且这似乎是多余的。不幸的是,我无法在不使用 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
}