Причина, по которой вы не можете добавить предварительные условия, - это та же причина, по которой вы не можете сделать это:
interface IInterface
{
void Foo(Parent x);
}
class Implementation : IInterface
{
void Foo(Child x);
}
Это связано с (со / против) дисперсией & mdash; Параметры метода противоречивы, то есть тип, который вы принимаете, должен быть «как минимум таким же большим / либеральным», как тип, указанный в интерфейсе.
Добавление большего количества предварительных условий делает тип меньше / более строгим, точно так же, как если бы был принят подкласс типа (как в примере выше). * Вы не можете сделать это по понятным причинам & mdash; класс, который реализует интерфейс, может не работать при передаче правильных аргументов! Если бы вы перевернули Parent
& Child
, все было бы в порядке.
С типами возвращаемых методов все наоборот: они ковариантны, то есть вы должны быть «хотя бы такими же маленькими / строгими», как тип, указанный в интерфейсе. Вот почему вы можете добавлять постусловия, потому что вы делаете тип «меньше / строже». По той же причине, по которой это работает:
interface IInterface
{
Parent Foo();
}
class Implementation : IInterface
{
Child Foo();
}
* (На самом деле возникает вопрос о том, сможете ли вы удалить предварительные условия из реализации классов. Это было бы интересной возможностью.)