Хорошие вопросы. Позвольте мне их переформулировать.
Почему вообще законно скрывать метод с помощью другого метода?
Позвольте мне ответить на этот вопрос примером. У вас есть интерфейс из CLR v1:
interface IEnumerable
{
IEnumerator GetEnumerator();
}
Супер. Теперь в CLR v2 у вас есть дженерики, и вы думаете: «Блин, если бы у нас были дженерики в v1, я бы сделал его универсальным интерфейсом. Но я этого не сделал. Я должен сделать что-то совместимое с ним сейчас, что является универсальным, чтобы Я получаю преимущества универсальных шаблонов без потери обратной совместимости с кодом, ожидающим IEnumerable ».
interface IEnumerable<T> : IEnumerable
{
IEnumerator<T> .... uh oh
Для чего вы собираетесь вызывать метод GetEnumerator IEnumerable<T>
? Помните, что вы хотите, чтобы GetEnumerator был скрыт в неуниверсальном базовом интерфейсе. Вы никогда не захотите, чтобы эта вещь вызывалась, если вы явно не находитесь в ситуации обратной совместимости.
Одно это оправдывает сокрытие метода. Дополнительные мысли об обосновании скрытия метода см. В моей статье на эту тему .
Почему скрытие без «нового» вызывает предупреждение?
Потому что мы хотим обратить ваше внимание на то, что вы что-то скрываете и, возможно, делаете это случайно. Помните, что вы могли случайно что-то скрыть из-за изменения базового класса, сделанного кем-то другим, а не в результате редактирования производного класса.
Почему скрытие без «нового» является предупреждением, а не ошибкой?
Той же причине. Возможно, вы случайно что-то скрываете, потому что только что приобрели новую версию базового класса. Это происходит все время. FooCorp создает базовый класс B. BarCorp создает производный класс D с методом Bar, потому что их клиентам нравится этот метод. FooCorp видит это и говорит: «Эй, это хорошая идея, мы можем добавить эту функциональность в базовый класс». Они поступают так и выпускают новую версию Foo.DLL, и когда BarCorp подберет новую версию, было бы неплохо, если бы им сказали, что их метод теперь скрывает метод базового класса.
Мы хотим, чтобы эта ситуация была предупреждением, а не ошибкой, потому что создание ошибки означает, что это еще одна форма проблемы хрупкого базового класса . C # был тщательно разработан, чтобы при изменении базового класса влияние на код, использующий производный класс, сводилось к минимуму.
Почему скрывается, а не отменяется значение по умолчанию?
Потому что виртуальное переопределение опасно . Виртуальное переопределение позволяет производным классам изменять поведение кода, который был скомпилирован для использования базовых классов. Совершать что-то опасное, например, отменять, следует делать сознательно и намеренно , а не случайно.