Кодовые контракты, общие и пользовательские перечислимые

Я использую С# 4.0 и Code Contracts, и у меня есть свой собственный 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?

EDIT:

Добавление ссылки для объекта перед итерацией также не работает:

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: Может ли проблема как-то быть связана с этим вопросом?

Ответ 1

Я думаю, что это может иметь отношение к чистоте метода GetEnumerator. PureAttribute

Контракты принимают только методы, которые определены как [Pure] (свободный побочный эффект).

Дополнительная информация Кодовые контракты, посмотрите на чистоту

Qoute:

Чистота

Все методы, вызываемые внутри договор должен быть чистым; то есть они не должно обновлять существующее существо. Чистый метод разрешается изменять объекты, созданные после вход в чистый метод.

В настоящее время используются инструменты контрактного контракта что следующие элементы кода чистый:

Методы, отмеченные PureAttribute.

Типы, отмеченные PureAttribute (применяется атрибут ко всем типам методов).

Получить доступ к свойствам.

Операторы (статические методы, чьи имена начните с "op", и у вас есть один или два параметра и непустое возвращение тип).

Любой метод, чье полное имя начинается с "System.Diagnostics.Contracts.Contract", "System.String", "System.IO.Path" или "System.Type".

Любой вызванный делегат при условии, что сам тип делегата с PureAttribute. Делегат типы System.Predicate и Рассматривается система. Сравнение чистый.

Ответ 2

Я подозреваю, потому что model.AllGameRooms возвращает IEnumerable<GameRoom>, который может быть различным при каждом доступе к ресурсу.

Попробуйте использовать:

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