Объяснение
В разделе 3: Наследование контрактов в руководстве пользователя говорится, что все предварительные условия должны быть определены в корневом методе цепочки наследования / реализации:
Если клиент удостоверяется, что он выполнил предварительное условие, и имеет переменную o
, статический тип которой равен T
, то клиент не должен получать нарушение предварительного условия, когда он вызывает o.M
.Это должно быть верно, даже если значение времени выполнения o
имеет тип U
.Следовательно, метод U.M
не может добавить предварительное условие, более сильное, чем предварительное условие T.M
.
Хотя мы могли бы допустить более слабое предварительное условие, мы обнаружили, что осложнения, связанные с этим, перевешивают преимущества.Мы просто не видели убедительных примеров, когда ослабление предварительного условия полезно.Поэтому мы вообще не разрешаем добавлять какие-либо предварительные условия в подтип.
Как следствие, предварительные условия метода должны быть объявлены в корневом методе цепочки наследования / реализации, т. Е. В первом объявлении виртуального или абстрактного метода,или сам метод интерфейса.
Решение
В вашей ситуации наилучшим способом действий является установка инварианта, утверждающего, что поле _somethingElse
никогда не является нулевым:
[ContractInvariantMethod]
private void ObjectInvariant() {
Contract.Invariant(_somethingElse != null);
}
Это, конечно, всегда верно, поскольку поле помечено readonly
и инициализировано в конструкторе.Статическая проверка не может определить это сама по себе, поэтому вы должны явно указать это через этот инвариант.
Вы можете дополнительно добавить постусловие Contract.Ensures(_somethingElse != null);
в свой конструктор, но статическая проверка не делаетэто не требуется.