Poniżej znajduje się pytanie do wywiadu. Wymyśliłem rozwiązanie, ale nie jestem pewien, dlaczego działa.
Pytanie:
Bez modyfikowania Sparta
klasy napisz kod, który spowoduje MakeItReturnFalse
zwrot false
.
public class Sparta : Place
{
public bool MakeItReturnFalse()
{
return this is Sparta;
}
}
Moje rozwiązanie: (SPOILER)
public class Place
{
public interface Sparta { }
}
Ale dlaczego Sparta
w MakeItReturnFalse()
odnosi się {namespace}.Place.Sparta
zamiast {namespace}.Sparta
?
c#
inheritance
types
namespaces
budi
źródło
źródło
Odpowiedzi:
Zasadniczo dlatego, że tak mówią reguły wyszukiwania nazw. W specyfikacji C # 5 odpowiednie reguły nazewnictwa znajdują się w sekcji 3.8 („Przestrzenie nazw i nazwy typów”).
Pierwsze kilka punktorów - skrócone i opatrzone adnotacjami - czytaj:
Tak więc ostatni punkt jest tym, co podnosi
Sparta
klasę, jeśli pierwszy punktor niczego nie znajdzie ... ale kiedy klasa bazowaPlace
definiuje interfejsSparta
, zostaje znaleziona, zanim rozważymySparta
klasę.Zwróć uwagę, że jeśli ustawisz typ zagnieżdżony
Place.Sparta
jako klasę, a nie interfejs, nadal kompiluje się i zwracafalse
- ale kompilator wyświetla ostrzeżenie, ponieważ wie, że instancja klasySparta
nigdy nie będzie instancją tej klasyPlace.Sparta
. Podobnie, jeśli zachowaszPlace.Sparta
interfejs, ale utworzyszSparta
klasęsealed
, otrzymasz ostrzeżenie, ponieważ żadnaSparta
instancja nie może zaimplementować interfejsu.źródło
Sparta
klasythis is Place
zwracatrue
. Jednak dodaniepublic interface Place { }
doSparta
klasy powodujethis is Place
powrótfalse
. Kręci mi się w głowie.Place
jako interfejs.Przy tłumaczeniu nazwy na jej wartość, „bliskość” definicji służy do rozwiązywania niejednoznaczności. Każda definicja jest „najbliższa” jest tą, która jest wybrana.
Interfejs
Sparta
jest zdefiniowany w klasie bazowej. KlasaSparta
jest zdefiniowana w zawierającej przestrzeń nazw. Rzeczy zdefiniowane w klasie bazowej są „bliżej” niż rzeczy zdefiniowane w tej samej przestrzeni nazw.źródło
Piękne pytanie! Chciałbym dodać nieco dłuższe wyjaśnienie dla tych, którzy na co dzień nie robią C # ... ponieważ to pytanie jest dobrym przypomnieniem ogólnych problemów z rozwiązywaniem nazw.
Weź oryginalny kod, nieznacznie zmodyfikowany w następujący sposób:
return this is Sparta
.).Athena
wPlace
nadklasie, aby zilustrować rozwiązywanie nazw interfejsów.this
ponieważ jest ona związana wSparta
klasie, aby wszystko było bardzo jasne.Kod wygląda następująco:
Teraz tworzymy
Sparta
obiekt i wywołujemy trzy metody.Wynik, jaki otrzymujemy, to:
Jeśli jednak zmodyfikujemy klasę Place i zdefiniujemy interfejs Sparta:
to właśnie ten
Sparta
- interfejs - będzie dostępny jako pierwszy dla mechanizmu wyszukiwania nazw, a wynik naszego kodu zmieni się na:Tak więc skutecznie pomieszaliśmy porównanie typów w
MakeItReturnFalse
definicji funkcji, po prostu definiując interfejs Sparty w nadklasie, który znajduje się jako pierwszy na podstawie rozpoznawania nazw.Ale dlaczego C # wybrał priorytetyzację interfejsów zdefiniowanych w nadklasie w rozpoznawaniu nazw? @JonSkeet wie! A jeśli przeczytasz jego odpowiedź, zobaczysz szczegóły protokołu rozpoznawania nazw w C #.
źródło