Anscheinend ist C # für "& gt; & gt;" lexer dilemma wie auch C ++ .
Dieser C # -Code ist ziemlich gültig, er kompiliert und läuft gut:
%Vor%Sie müssten '& lt; überladen' und "& gt; & gt;" Operatoren für die Dummy-Klasse oben.
Aber der Compiler kann raten, dass im 'x' Fall die lokalen Variablen List, Nullable und Guid verwendet werden. Und im, y 'Fall beschließt es plötzlich, sie als Namen bekannter Typen zu behandeln.
Hier ist ein bisschen detailliertere Beschreibung mit einem anderen Beispiel: Ссылка
Die Frage ist: Wie löst der C # -Compiler 'a & lt; b & lt; c & gt; & gt;' zum arithmetischen Ausdruck oder generischen Typ / Methode?
Sicherlich versucht es nicht, mehrfach über den Text des Programms zu gehen, bis es gelingt, oder? Das würde unbegrenzte Vorausschau erfordern und auch sehr komplex.
Ich wurde auf den Abschnitt 7.6.4.2 in der C # -Sprachspezifikation verwiesen:
Die Produktionen für Simple-Name (§7.6.2) und Member-Access (§7.6.4) können zu Mehrdeutigkeiten in der Grammatik für Ausdrücke führen.
...
Wenn eine Folge von Token als ein einfacher Name (im Kontext) (§7.6.2), Member-Zugriff (§7.6.4) oder Zeiger-Mitglied-Zugriff (§18.5.2) geendet werden kann mit einer Typ-Argument-Liste (§4.4.1), das Token unmittelbar nach dem Schließen & gt; Token wird überprüft. Wenn es eines von
ist()]}:; . ? ==! = | ^
dann wird die Typ-Argument-Liste als Teil des Einfach-Namens, Mitglieder-Zugriffs oder Zeiger-Mitglied-Zugriffs beibehalten und jede andere mögliche Syntaxanalyse der Token-Sequenz wird verworfen. Andernfalls wird die Typ-Argument-Liste nicht als Teil des einfachen Namens, des Member-Zugriffs oder des Zeiger-Mitglied-Zugriffs betrachtet, selbst wenn es keine andere mögliche Syntaxanalyse der Folge von Token gibt. Beachten Sie, dass diese Regeln nicht angewendet werden, wenn Sie eine Typ-Argument-Liste in einem Namensraum-oder-Typ-Namen (§3.8) analysieren.
Es kann also zu einer Zweideutigkeit kommen, wenn eine Typ-Argument-Liste involviert ist, und sie haben einen billigen Weg, sie zu lösen, indem sie einen Token voraus schauen.
Es ist immer noch ein ungebundener Blick nach vorn, denn zwischen "& gt; & gt;" und folgen Token, aber zumindest ist die Regel mehr oder weniger klar. Und am wichtigsten ist, dass keine spekulative Tiefenanalyse benötigt wird.
EDIT: Ich bestehe darauf, dass es keine Zweideutigkeit gibt:
In Ihrem Beispiel gibt es keine Zweideutigkeit. Dies könnte niemals als List<Guid?>
ausgewertet werden. Der Kontext (die zusätzlichen 10) zeigt dem Compiler, wie er zu interpretieren ist.
Würde der Compiler dies kompilieren?:
%Vor%Es ist klar, dass es nicht so wäre. Also bin ich immer noch auf der Suche nach der Mehrdeutigkeit.
OTOH, der zweite Ausdruck:
%Vor% muss als List<Guid?>
ausgewertet werden, da Sie die Methode .Equals
aufrufen. Auch dies kann auf andere Weise interpretiert werden.
Es gibt kein Paradoxon. Der Compiler analysiert es perfekt. Ich frage mich immer noch, was die Apradox ist.
Sie haben einen großen Fehler. Der Compiler interpretiert ganze Ausdrücke und verwendet die Sprachgrammatik, um sie zu verstehen. Es betrachtet kein Code-Fragment, wie Sie es tun, ohne den Rest des Ausdrucks zu berücksichtigen.
Diese Ausdrücke werden gemäß zur C # -Grammatik analysiert. Und die Grammatik ist klar genug, um den Code richtig zu interpretieren. I.e. in
%Vor% Es ist klar, dass 10 ein Literal ist. Wenn Sie die Grammatik nachverfolgen, finden Sie Folgendes: 10 ist ein * literal , also ist es primary-no-array-creation-expression , was ein *
Wenn Sie einen anderen Weg finden könnten, die Grammatik zu verwenden und ein anderes Ergebnis für denselben Ausdruck zu erhalten, dann müsste ich Ihnen zustimmen, aber lassen Sie mich widersprechen!
Schließlich:
Weil:
List<Nullable<Guid>>
, aufnehmen und sie so interpretieren, wie wir wollen List<Nullable<Guid>>
. Sie nehmen den ganzen Ausdruck und passen ihn der Grammatik der Sprache an. Tags und Links c# lexer nested-generics