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