Следующее - вопрос интервью. Я нашел решение, но не знаю, почему оно работает.
Вопрос:
Не изменяя Sparta
класс, напишите код, MakeItReturnFalse
возвращающий результат false
.
public class Sparta : Place
{
public bool MakeItReturnFalse()
{
return this is Sparta;
}
}
Мое решение: (СПОЙЛЕР)
public class Place
{
public interface Sparta { }
}
Но почему Sparta
in MakeItReturnFalse()
относится к {namespace}.Place.Sparta
вместо {namespace}.Sparta
?
c#
inheritance
types
namespaces
буди
источник
источник
Ответы:
В основном потому, что так говорят правила поиска имени. В спецификации C # 5 соответствующие правила именования находятся в разделе 3.8 («Пространство имен и имена типов»).
Первая пара пунктов - усеченная и снабженная аннотациями - гласила:
Таким образом, последний пункт маркера - это то, что выбирает
Sparta
класс, если первый маркер ничего не находит ... но когда базовый классPlace
определяет интерфейсSparta
, он обнаруживается до того, как мы рассмотримSparta
класс.Обратите внимание, что если вы сделаете вложенный тип
Place.Sparta
классом, а не интерфейсом, он все равно компилируется и возвращается,false
но компилятор выдает предупреждение, потому что он знает, что экземплярSparta
никогда не будет экземпляром классаPlace.Sparta
. Точно так же, если вы сохранитеPlace.Sparta
интерфейс, но создадитеSparta
классsealed
, вы получите предупреждение, потому что ни одинSparta
экземпляр не сможет реализовать интерфейс.источник
Sparta
класс . Однако добавление к классу приводит к возврату . Голова кружится.this is Place
true
public interface Place { }
Sparta
this is Place
false
Place
качестве интерфейса используется предыдущий пункт .При преобразовании имени в его значение «близость» определения используется для разрешения двусмысленностей. Какое бы определение ни было «наиболее близким», оно будет выбрано.
Интерфейс
Sparta
определяется в базовом классе. КлассSparta
определен в содержащем пространстве имен. Вещи, определенные в базовом классе, «ближе», чем вещи, определенные в том же пространстве имен.источник
Прекрасный вопрос! Я хотел бы добавить немного более подробное объяснение для тех, кто не занимается C # каждый день ... потому что этот вопрос является хорошим напоминанием о проблемах с разрешением имен в целом.
Возьмите исходный код, немного измененный следующим образом:
return this is Sparta
).Athena
вPlace
суперклассе, чтобы проиллюстрировать разрешение имени интерфейса.this
, связанное сSparta
классом, чтобы все было очень понятно.Код выглядит так:
Теперь мы создаем
Sparta
объект и вызываем три метода.Результат, который мы получаем:
Однако, если мы изменим класс Place и определим интерфейс Sparta:
тогда именно этот
Sparta
интерфейс будет доступен в первую очередь механизму поиска имени, и вывод нашего кода изменится на:Таким образом, мы фактически испортили сравнение типов в
MakeItReturnFalse
определении функции, просто определив интерфейс Sparta в суперклассе, который сначала находится по разрешению имен.Но почему C # выбрал приоритет интерфейсов, определенных в суперклассе, в разрешении имен? @JonSkeet знает! И если вы прочитаете его ответ, вы получите подробную информацию о протоколе разрешения имен в C #.
источник