Зачем мне нужно переопределять ограничение типа в общем подклассе

Недавно я попытался создать общий подкласс, выполнив общий интерфейс.

public interface IModule<T> where T : DataBean { ..... }
public class Module<T> : IModule<T> where T : DataBean { .... } 

Кажется, я не могу полагаться на какие-либо ограничения T, которые были определены в базовом интерфейсе, и мне нужно снова объявить их.

MSDN только что предоставлено:

При использовании подкласса типа generic параметров, вы должны повторить ограничения, предусмотренные на базе уровня класса на уровне подкласса. Для пример, ограничение деривации

Почему не возможно вывести ограничения из базового класса/интерфейса?

Ответы

Ответ 1

Я не могу придумать, почему С# не может теоретически скопировать ограничения. Но документированное поведение, позволяющее нам копировать (или увеличивать) их явно, является самым простым способом для удобства использования.

public class A{}
public class B : A {}

public class X<T> where T: A {}
public class Y<T> : X<T> where T: B { }

В приведенном выше примечании обратите внимание, что мне не нужно было копировать выражение по ограничению на Y<T>, потому что B всегда является A.

Теперь давайте посмотрим, что произойдет, если "компилятор автоматически копирует ограничения". Скажем, я определяю Y<T> без ограничений, и компилятор помещает их автоматически. Я использую Y<T> в большом количестве кода. Затем я изменяю ограничения на объявление X<T>, чтобы включить некоторый новый интерфейс.

Ошибки компилятора для изменения объявления X<T> находятся на сайтах, где я использую Y<T>!

С тем, как в настоящее время работает компилятор С#, ошибки компилятора имеют значения X<T>, как я ожидал бы, если я изменю его на разрыв.

Поэтому, хотя это было бы удобно в некоторых сценариях, это также было бы несколько запутанным в других. Хотя оба являются действительными подходами, я бы предположил (обратите внимание, что я не умею читать умы команды разработчиков С#), что это был призыв к суждению, а не чисто технический.

Я говорю "не чисто технический", но я могу себе представить некоторые сценарии интерфейса, где было бы проще проверить, что все ограничения выполнены, а не создавать простейшее ограничение, отвечающее всем требуемым унаследованным ограничениям.

Ответ 2

Командная мудрость Standard С#. Декларации должны быть самодокументированы. И самое главное, изменение объявления одного типа не должно изменять поведение несвязанного другого типа без генерации диагностики. Принцип -100 пунктов, введенный в конструкцию, - это еще один подход.

Ответ 3

Контрайны на интерфейсе слишком велики, чтобы сообщить компилятору, какие ограничения должен иметь класс модуля. Например, класс модуля может иметь ограничение на суперкласс (унаследованный класс) DataBean.

Я не знаю мудрости дизайнеров С#. Поскольку ограничения могут быть разными, я думаю, было принято решение о том, что разработчик явно объявляет ограничение, а не компилятор делает предположения.