代码合约、forall 和自定义可枚举

发布于 2024-10-17 20:12:13 字数 1728 浏览 9 评论 0原文

我正在使用 C# 4.0 和代码合约,并且有自己的自定义 GameRoomCollection : IEnumerable

我想确保 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 

编辑2:

但是:如果我将游戏室集合类型转换为数组,它可以正常工作:

IGameRoom[] gameRoomArray = model.AllGameRooms.ToArray();
Contract.Assume(Contract.ForAll(gameRoomArray, g => g != null));
foreach (IGameRoom gameRoom in gameRoomArray)
    SetupListeners(gameRoom);//<= NO WARNING

是这是因为您无法为 IEnumerable 接口的方法定义规则?

编辑3:问题是否与这个问题?

I am using C# 4.0 and Code Contracts and I have my own custom GameRoomCollection : IEnumerable<GameRoom>.

I want to ensure, that no instances of GameRoomCollection will ever contain a null value element. I don't seem to be able to this, though. Instead of making a general rule, I have tried to do a plain and simple example. The AllGameRooms is an instance of 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 
}

Can anyone see, why I haven't proven, that gameRoom is not null?

EDIT:

Adding a reference for the object before iterating does not work either:

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:

However: If I convert the game room collection type to an array, it works fine:

IGameRoom[] gameRoomArray = model.AllGameRooms.ToArray();
Contract.Assume(Contract.ForAll(gameRoomArray, g => g != null));
foreach (IGameRoom gameRoom in gameRoomArray)
    SetupListeners(gameRoom);//<= NO WARNING

Is this caused by the fact, that you cannot define a rule for methods of the IEnumerable<T> interface?

EDIT3: Can the problem somehow be related to this question?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤独陪着我 2024-10-24 20:12:13

我认为这可能与 GetEnumerator 方法的纯度有关。 PureAttribute

合约仅接受定义为的方法[纯](无副作用)。

一些额外信息代码契约,寻找纯度

引用:

纯度

在一个内部调用的所有方法
合同必须是纯粹的;也就是说,他们
不得更新任何预先存在的状态。
允许修改纯方法
之后创建的对象
进入纯方法。

代码合约工具当前假设
以下代码元素是
纯:

标有的方法
纯属性。

标有的类型
PureAttribute(属性适用
所有类型的方法)。

属性获取访问器。

运算符(静态方法,其名称
以“op”开头,并且有一个或
两个参数和一个非空返回值
类型)。

任何具有完全限定名称的方法
开始于
“系统.诊断.合同.合同”,
“System.String”、“System.IO.Path”或
“系统.类型”。

任何调用的委托,前提是
委托类型本身具有属性
与 PureAttribute 一起。代表
类型 System.Predicate 和
System.Comparison被考虑
纯净。

I think this might have to do with purity of the GetEnumerator method. PureAttribute

Contracts only accept methods that are defined as [Pure] (side effect free).

Some extra information Code Contracts, look for purity

Qoute:

Purity

All methods that are called within a
contract must be pure; that is, they
must not update any preexisting state.
A pure method is allowed to modify
objects that have been created after
entry into the pure method.

Code contract tools currently assume
that the following code elements are
pure:

Methods that are marked with the
PureAttribute.

Types that are marked with the
PureAttribute (the attribute applies
to all the type's methods).

Property get accessors.

Operators (static methods whose names
start with "op", and that have one or
two parameters and a non-void return
type).

Any method whose fully qualified name
begins with
"System.Diagnostics.Contracts.Contract",
"System.String", "System.IO.Path", or
"System.Type".

Any invoked delegate, provided that
the delegate type itself is attributed
with the PureAttribute. The delegate
types System.Predicate and
System.Comparison are considered
pure.

离不开的别离 2024-10-24 20:12:13

我怀疑这是因为 model.AllGameRooms 返回一个 IEnumerable ,它在每个属性访问上可能不同。

尝试使用:

var gameRooms = mode.AllGameRooms;
Contract.Assume(Contract.ForAll(gameRooms, g => g != null));
foreach (IGameRoom gameRoom in gameRooms)
    SetupListeners(gameRoom);    

I suspect it's because model.AllGameRooms returns an IEnumerable<GameRoom> which could be different on each property access.

Try using:

var gameRooms = mode.AllGameRooms;
Contract.Assume(Contract.ForAll(gameRooms, g => g != null));
foreach (IGameRoom gameRoom in gameRooms)
    SetupListeners(gameRoom);    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文