代码合同,forall和custom可枚举

时间:2011-02-17 22:47:06

标签: c# code-contracts enumerable forall

我正在使用C#4.0和代码合同,我有自己的自定义GameRoomCollection : IEnumerable<GameRoom>

我想确保GameRoomCollection的任何实例都不会包含null值元素。不过,我似乎无法做到这一点。我试图做一个简单明了的例子,而不是制定一般规则。 AllGameRoomsGameRoomCollection的实例。

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有关吗?​​

2 个答案:

答案 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);