Das Folgende ist eine Interviewfrage. Ich habe eine Lösung gefunden, bin mir aber nicht sicher, warum sie funktioniert.
Frage:
Sparta
Schreiben Sie einen Code, der die MakeItReturnFalse
Rückgabe bewirkt, ohne die Klasse zu ändern false
.
public class Sparta : Place
{
public bool MakeItReturnFalse()
{
return this is Sparta;
}
}
Meine Lösung: (SPOILER)
public class Place
{
public interface Sparta { }
}
Aber warum bezieht sich Sparta
in MakeItReturnFalse()
auf {namespace}.Place.Sparta
statt {namespace}.Sparta
?
c#
inheritance
types
namespaces
budi
quelle
quelle
Antworten:
Grundsätzlich, denn das sagen die Namenssuchregeln. In der C # 5-Spezifikation finden Sie die relevanten Namensregeln in Abschnitt 3.8 ("Namespace- und Typnamen").
Die ersten paar Kugeln - abgeschnitten und kommentiert - lauteten:
Dieser letzte Punkt ist es also, der die Klasse aufnimmt
Sparta
wenn der erste Aufzählungspunkt nichts findet ... aber wenn die BasisklassePlace
eine Schnittstelle definiertSparta
, wird sie gefunden, bevor wir dieSparta
Klasse betrachten.Beachten Sie, dass der verschachtelte Typ, wenn Sie ihn zu
Place.Sparta
einer Klasse und nicht zu einer Schnittstelle machen, weiterhin kompiliert und zurückgegeben wird.false
Der Compiler gibt jedoch eine Warnung aus, da er weiß, dass eine Instanz vonSparta
niemals eine Instanz der Klasse sein wirdPlace.Sparta
. Wenn SiePlace.Sparta
eine Schnittstelle behalten , aber dieSparta
Klasse erstellensealed
, erhalten Sie ebenfalls eine Warnung, da keineSparta
Instanz die Schnittstelle jemals implementieren könnte.quelle
Sparta
Klasse wirdthis is Place
zurückgegebentrue
. Das Hinzufügenpublic interface Place { }
zurSparta
Klasse führt jedochthis is Place
zur Rückkehrfalse
. Lässt meinen Kopf drehen.Place
als Schnittstelle.Beim Auflösen eines Namens auf seinen Wert wird die "Nähe" der Definition verwendet, um Mehrdeutigkeiten aufzulösen. Welche Definition auch immer "am nächsten" ist, es wird gewählt.
Die Schnittstelle
Sparta
wird innerhalb einer Basisklasse definiert. Die KlasseSparta
wird im enthaltenen Namespace definiert. Innerhalb einer Basisklasse definierte Dinge sind "näher" als Dinge, die im selben Namespace definiert sind.quelle
Schöne Frage! Ich möchte eine etwas längere Erklärung für diejenigen hinzufügen, die nicht täglich C # machen ... weil die Frage eine gute Erinnerung an Probleme mit der Namensauflösung im Allgemeinen ist.
Nehmen Sie den Originalcode, der auf folgende Weise leicht modifiziert wurde:
return this is Sparta
) zu vergleichen.Athena
in derPlace
Oberklasse, um die Auflösung des Schnittstellennamens zu veranschaulichen.this
in derSparta
Klasse gebunden ist , um alles sehr klar zu machen.Der Code sieht folgendermaßen aus:
Wir erstellen nun ein
Sparta
Objekt und rufen die drei Methoden auf.Die Ausgabe, die wir erhalten, ist:
Wenn wir jedoch die Place-Klasse ändern und die Schnittstelle Sparta definieren:
Dann ist es diese
Sparta
- die Schnittstelle -, die zuerst für den Namenssuchmechanismus verfügbar ist, und die Ausgabe unseres Codes ändert sich zu:Wir haben also den Typvergleich in der
MakeItReturnFalse
Funktionsdefinition effektiv durcheinander gebracht, indem wir die Sparta-Schnittstelle in der Oberklasse definiert haben, die zuerst durch die Namensauflösung ermittelt wird.Aber warum hat C # in der Namensauflösung in der Oberklasse definierte Schnittstellen priorisiert? @ JonSkeet weiß! Und wenn Sie seine Antwort lesen, erhalten Sie die Details des Namensauflösungsprotokolls in C #.
quelle