Что означает Эрик Липпер, "вам нужно знать, что базовый класс должен определить, что такое базовый класс"?
Я просто прочитал эту интересную статью Эрика Липперта, Топ-10 худших функций С#. Ближе к концу он утверждает:
Правила для разрешения имен после вышеупомянутого двоеточия не являются хорошо обоснованный; вы можете оказаться в ситуациях, когда вам нужно знать, что базовый класс должен определить, что такое базовый класс.
По двоеточию он ссылается на оператор наследования (например, Dog : Animal
).
В какой ситуации относится Эрик? Может ли кто-нибудь предоставить образец кода?
Ответы
Ответ 1
Это может произойти в свернутых сценариях с дженериками, наследованием и вложенными классами:
class Base<T> {
public class Inner {}
}
class Derived : Base<Derived.Inner2> {
public class Inner2 : Inner {}
}
Результат
- Чтобы определить базовый класс
Derived
, нам нужно привязать Derived.Inner2
.
- Чтобы связать
Derived.Inner2
, нам нужно разрешить символ Inner
.
- Символ
Inner
наследуется от его содержащего базовый класс видимости, поэтому нам нужно снова определить базовый класс Derived
.
Ответ 2
SLaks дает хороший ответ; см. мои комментарии для некоторых дополнительных заметок.
Как я уже сказал в комментариях, я ищу свои старые заметки по этому вопросу, и если я их найду, я напишу блог. Здесь интересный дополнительный пример. Эта программа является законной. Являются ли значения N
в декларации класса и полевые декларации одинаковыми или разными? Если они одинаковы, что для них является полностью квалифицированным типом? Если они разные, почему спецификация требует, чтобы они были разными?
public class N {}
public class B<T>
{
public class N {}
}
public class D : B<N> // base class
{
N n; // field
}
Это иллюстрирует основную проблему: поиск имени требует, чтобы базовый класс был известен, но базовый класс просматривается по имени.
Теперь подумайте о том, как интерфейсы работают в миксе. Предположим, что класс D
также реализует интерфейс IN
, аналогично вложенный в B
и доступный глобально. Определяет ли интерфейс поиск базового класса или глобального пространства имен? Это те вопросы, которые вы должны решить, когда пишете компилятор.