Красиве запитання! Я хотів би додати трохи довше пояснення для тих, хто не робить C # щодня ... тому що це питання добре нагадує проблеми вирішення імен загалом.
Візьміть оригінальний код, трохи змінений наступними способами:
- Давайте надрукуємо назви типів, а не порівнюємо їх як у вихідному виразі (тобто
return this is Sparta
).
- Давайте визначимо інтерфейс
Athena
у Place
суперкласі для ілюстрації роздільної здатності імені інтерфейсу.
- Давайте також надрукуємо ім'я типу, яке
this
воно пов'язане в Sparta
класі, щоб зробити все дуже зрозумілим.
Код виглядає так:
public class Place {
public interface Athena { }
}
public class Sparta : Place
{
public void printTypeOfThis()
{
Console.WriteLine (this.GetType().Name);
}
public void printTypeOfSparta()
{
Console.WriteLine (typeof(Sparta));
}
public void printTypeOfAthena()
{
Console.WriteLine (typeof(Athena));
}
}
Тепер ми створюємо Sparta
об'єкт і викликаємо три методи.
public static void Main(string[] args)
{
Sparta s = new Sparta();
s.printTypeOfThis();
s.printTypeOfSparta();
s.printTypeOfAthena();
}
}
Вихід, який ми отримуємо:
Sparta
Athena
Place+Athena
Однак якщо ми змінимо клас Place і визначимо інтерфейс Sparta:
public class Place {
public interface Athena { }
public interface Sparta { }
}
тоді саме цей Sparta
інтерфейс буде доступний спочатку механізму пошуку імен, а вихід нашого коду зміниться на:
Sparta
Place+Sparta
Place+Athena
Таким чином, ми ефективно переплутали порівняння типів у MakeItReturnFalse
визначенні функції, просто визначивши інтерфейс Спарти в надкласі, який знаходимо спочатку за роздільною здатністю імені.
Але чому C # вирішив розставити пріоритети інтерфейсам, визначеним в суперкласі в роздільній здатності імені? @JonSkeet знає! І якщо ви прочитаєте його відповідь, ви отримаєте деталі протоколу вирішення імені в C #.