Warum funktioniert dieser Code? Ich verwende C # 8 mit Visual Studio 2019.
Sie haben Ihre eigene Frage beantwortet! Das liegt daran, dass Sie C # 8 verwenden.
Die Regel von C # 1 bis 7 lautete: Ein einfacher Name kann nicht verwendet werden, um zwei verschiedene Dinge im selben lokalen Bereich zu bedeuten. (Die eigentliche Regel war etwas komplexer als diese, beschreibt jedoch, wie langwierig sie ist. Einzelheiten finden Sie in der C # -Spezifikation.)
Die Absicht dieser Regel war es, die Art von Situation zu verhindern, von der Sie in Ihrem Beispiel sprechen, in der es sehr leicht wird, über die Bedeutung des Lokalen verwirrt zu werden. Diese Regel wurde insbesondere entwickelt, um Verwirrungen wie:
class C
{
int x;
void M()
{
x = 123;
if (whatever)
{
int x = 356;
...
Und jetzt haben wir eine Situation, in der im Körper von M
, x
sowohl this.x
als auch lokal bedeutet x
.
Obwohl gut gemeint, gab es eine Reihe von Problemen mit dieser Regel:
- Es wurde nicht nach Spezifikation implementiert. Es gab Situationen, in denen ein einfacher Name beispielsweise sowohl als Typ als auch als Eigenschaft verwendet werden konnte, diese wurden jedoch nicht immer als Fehler gekennzeichnet, da die Fehlererkennungslogik fehlerhaft war. (Siehe unten)
- Die Fehlermeldungen waren verwirrend formuliert und uneinheitlich gemeldet. Für diese Situation gab es mehrere verschiedene Fehlermeldungen. Sie identifizierten den Täter uneinheitlich; das heißt, manchmal wurde der innere Gebrauch gerufen, manchmal der äußere , und manchmal war es nur verwirrend.
Ich bemühte mich beim Umschreiben von Roslyn, dies zu klären. Ich habe einige neue Fehlermeldungen hinzugefügt und die alten konsistent gemacht, um festzustellen, wo der Fehler gemeldet wurde. Dieser Aufwand war jedoch zu gering, zu spät.
Das C # -Team entschied für C # 8, dass die gesamte Regel mehr Verwirrung stiftete als verhinderte, und die Regel wurde aus der Sprache entfernt. (Vielen Dank an Jonathon Chase für die Feststellung, wann der Ruhestand eingetreten ist.)
Wenn Sie daran interessiert sind, die Geschichte dieses Problems zu erfahren und zu erfahren, wie ich versucht habe, es zu beheben, lesen Sie die folgenden Artikel, die ich darüber geschrieben habe:
https://ericlippert.com/2009/11/02/simple-names-are-not-so-simple/
https://ericlippert.com/2009/11/05/simple-names-are-not-so-simple-part-two/
https://ericlippert.com/2014/09/25/confusing-errors-for-a-confusing-feature-part-one/
https://ericlippert.com/2014/09/29/confusing-errors-for-a-confusing-feature-part-two/
https://ericlippert.com/2014/10/03/confusing-errors-for-a-confusing-feature-part-three/
Am Ende des dritten Teils stellte ich fest, dass es auch eine Wechselwirkung zwischen dieser Funktion und der Funktion "Farbe Farbe" gab - dh der Funktion, die Folgendes ermöglicht:
class C
{
Color Color { get; set; }
void M()
{
Color = Color.Red;
}
}
Hier haben wir den einfachen Namen verwendet Color
, um sowohl auf this.Color
den aufgezählten Typ als auch auf den aufgezählten Typ zu verweisen Color
. Nach einer strengen Lektüre der Spezifikation sollte dies ein Fehler sein, aber in diesem Fall war die Spezifikation falsch und die Absicht war, dies zuzulassen, da dieser Code eindeutig ist und es ärgerlich wäre, den Entwickler dazu zu bringen, ihn zu ändern.
Ich habe diesen Artikel nie geschrieben, in dem all die seltsamen Wechselwirkungen zwischen diesen beiden Regeln beschrieben werden, und es wäre ein bisschen sinnlos, dies jetzt zu tun!
x
Parameter dieser Methode aus dem Bereich verschoben. Ein Beispiel finden Sie unter sharplab .