我正在使用C#4.0和代码合同,我有自己的自定义GameRoomCollection : IEnumerable<GameRoom>
。
我想确保GameRoomCollection
的任何实例都不会包含null
值元素。不过,我似乎无法做到这一点。我试图做一个简单明了的例子,而不是制定一般规则。 AllGameRooms
是GameRoomCollection
的实例。
private void SetupListeners(GameRoom newGameRoom) {
Contract.Requires(newGameRoom != null);
//...
}
private void SetupListeners(Model model) {
Contract.Requires(model != null);
Contract.Requires(model.AllGameRooms != null);
Contract.Assume(Contract.ForAll(model.AllGameRooms, g => g != null));
foreach (GameRoom gameRoom in model.AllGameRooms)
SetupListeners(gameRoom);//<= Warning: Code Contracts: Requires unproven: newGameRoom != null
}
有人可以看到,为什么我没有证明,gameRoom
不是null
?
修改
在迭代之前为对象添加引用也不起作用:
IEnumerable<IGameRoom> gameRooms = model.AllGameRooms;
Contract.Assume(Contract.ForAll(gameRooms, g => g != null));
foreach (IGameRoom gameRoom in gameRooms)
SetupListeners(gameRoom);//<= Warning: Code Contracts: Requires unproven: newGameRoom != null
EDIT2:
但是:如果我将游戏室集合类型转换为数组,它可以正常工作:
IGameRoom[] gameRoomArray = model.AllGameRooms.ToArray();
Contract.Assume(Contract.ForAll(gameRoomArray, g => g != null));
foreach (IGameRoom gameRoom in gameRoomArray)
SetupListeners(gameRoom);//<= NO WARNING
这是否是由于您无法为IEnumerable<T>
接口的方法定义规则而引起的?
EDIT3:问题可能与this question有关吗?
答案 0 :(得分:2)
我认为这可能与GetEnumerator方法的纯度有关。 PureAttribute
合同只接受定义为[Pure](无副作用)的方法。
一些额外信息Code Contracts, look for purity
Qoute:
纯度
在a中调用的所有方法 合同必须是纯粹的;就是他们 不得更新任何先前存在的状态。 允许纯方法修改 之后创建的对象 进入纯方法。
目前假设代码合同工具 以下代码元素是 纯:
标有的方法 PureAttribute。
标有的类型 PureAttribute(该属性适用 所有类型的方法)。
属性获取访问者。
运算符(名称为的静态方法) 以“op”开头,并且有一个或者 两个参数和一个非void返回 类型)。
任何完全限定名称的方法 开始于 “System.Diagnostics.Contracts.Contract” “System.String”,“System.IO.Path”或 “System.Type的”。
任何被调用的委托,前提是 委托类型本身是归因的 使用PureAttribute。代表 类型System.Predicate和 考虑System.Comparison 纯的。
答案 1 :(得分:0)
我怀疑是因为model.AllGameRooms
会返回IEnumerable<GameRoom>
,但每次访问属性时都会有所不同。
尝试使用:
var gameRooms = mode.AllGameRooms;
Contract.Assume(Contract.ForAll(gameRooms, g => g != null));
foreach (IGameRoom gameRoom in gameRooms)
SetupListeners(gameRoom);