Зачем мне нужно повторно объявить ограничение типа в универсальном подклассе - PullRequest
15 голосов
/ 08 января 2011

Недавно я попытался создать универсальный подкласс путем реализации универсального интерфейса.

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

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

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

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

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

Ответы [ 3 ]

6 голосов
/ 09 января 2011

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

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>!

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

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

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

5 голосов
/ 09 января 2011

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

1 голос
/ 09 января 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...