Roslyn ist die neue Compiler-Plattform. Es wird nur zur Kompilierungszeit verwendet.
Paulo Morgado
2
@PauloMorgado das ist nicht wahr, Sie können Rosyln zur Laufzeit verwenden, um Dinge zu tun. Zum Beispiel einen Live-Code-Editor erstellen oder Rosylns Parsing-Zeug verwenden, um Dinge mit Bäumen oder Ausdrücken oder so etwas zu tun
Chris Marisic
@ ChrisMarisic das ist mein Eindruck, aber ich habe nicht geantwortet, da mein Wissen zu diesem Thema begrenzt ist (daher meine Frage). Ich bin auf Folgendes gestoßen : scriptcs.net , ein ziemlich gutes Beispiel für Roslyns Macht, und von dem ich glaube, dass es Laufzeit-Sachen macht, aber ich könnte mich irren, da ich nicht ganz gut darüber informiert bin.
Gigi
@ChrisMarisic, Sie sagen also, dass Sie Roslyn verwenden können, um Live-Code aus dem Quellcode zu erstellen, nicht aus der einen Binärdatei, die ausgeführt wird. Und Sie verwenden Roslyn immer noch, um die Quelle in Binärdateien umzuwandeln, die Roslyn nicht zum Ändern dieser Binärdateien verwenden. Wenn Sie Roslyn zur Laufzeit nicht unbedingt verwenden könnten, könnten Sie niemals Code kompilieren.
Paulo Morgado
Antworten:
119
Ja. nameof()wird zur Kompilierungszeit ausgewertet. Schauen Sie sich die neueste Version der Spezifikationen an:
Der Name des Ausdrucks ist eine Konstante. In allen Fällen wird nameof (...) zur Kompilierungszeit ausgewertet , um eine Zeichenfolge zu erstellen. Das Argument wird zur Laufzeit nicht ausgewertet und gilt als nicht erreichbarer Code (es wird jedoch keine Warnung "Nicht erreichbarer Code" ausgegeben).
Wie in den Kommentaren erwähnt, bedeutet dies, dass Sie bei der Verwendung nameofvon Typparametern in einem generischen Typ nicht erwarten, den Namen des tatsächlichen dynamischen Typs zu erhalten, der als Typparameter verwendet wird, sondern nur den Namen des Typparameters. Also das:
Ich wollte die Antwort von @ I3arnon mit einem Beweis bereichern, dass sie zur Kompilierungszeit ausgewertet wird.
Nehmen wir an, ich möchte den Namen einer Variablen in der Konsole mit dem nameofOperator drucken :
var firstname ="Gigi";var varname = nameof(firstname);Console.WriteLine(varname);// Prints "firstname" to the console
Wenn Sie die generierte MSIL auschecken, werden Sie feststellen, dass sie einer Zeichenfolgendeklaration entspricht, da ein Objektverweis auf eine Zeichenfolge mit dem ldstrOperator auf den Stapel verschoben wird:
Sie werden feststellen, dass das Deklarieren der Vorname-Zeichenfolge und die Verwendung des nameofOperators denselben Code in MSIL generiert. Dies bedeutet, dass dies nameofgenauso effizient ist wie das Deklarieren einer Zeichenfolgenvariablen.
Wenn die MSIL in Quellcode dekompiliert wird, wie leicht kann der Dekompiler erkennen, dass es sich um einen nameofOperator und nicht um eine einfache fest codierte Zeichenfolge handelt?
ADTC
11
Das ist eine gute Frage! Sie können es als neue Frage auf SO posten, wenn Sie eine detaillierte Erklärung erhalten möchten :) .. Die kurze Antwort lautet jedoch, dass der Dekompiler nicht herausfinden kann, dass es sich um einen Namen des Operators handelt, sondern stattdessen ein Zeichenfolgenliteral verwendet . Ich habe überprüft, dass dies bei ILSpy und Reflector der Fall ist.
Faris Zacina
2
@ADTC: Da der Name von vollständig durch Laden eines Strings auf den Stapel ersetzt wird, wie könnte der Dekompiler überhaupt versuchen, zu erraten, dass es sich um einen Namen und nicht um einen einfachen konstanten Parameter handelt?
Quetzalcoatl
2
Das ist interessant. Möglicherweise könnte der Dekompiler die Zeichenfolge mit dem aktuellen Kontext vergleichen (Name der Methode / Eigenschaft / usw., in der Sie sich befinden). Trotzdem gibt es keine Möglichkeit, 100% zuverlässig zu sein - vielleicht haben Sie doch einen fest codierten String verwendet.
Gigi
2
Obwohl ich damit einverstanden bin, dass Sie nach dem Kompilieren nicht wissen können, ob es sich um einen Namen handelt, sehe ich noch keinen Hinweis darauf, dass ILSpy oder Reflector C # 6 unterstützen. Wenn das der Fall ist, können Sie es nicht testen @TheMinister
Antworten:
Ja.
nameof()
wird zur Kompilierungszeit ausgewertet. Schauen Sie sich die neueste Version der Spezifikationen an:Vom Namen des Betreibers - v5
Sie können dies anhand dieses TryRoslyn-Beispiels sehen :
Wird dazu kompiliert und dekompiliert:
Das Laufzeitäquivalent lautet:
Wie in den Kommentaren erwähnt, bedeutet dies, dass Sie bei der Verwendung
nameof
von Typparametern in einem generischen Typ nicht erwarten, den Namen des tatsächlichen dynamischen Typs zu erhalten, der als Typparameter verwendet wird, sondern nur den Namen des Typparameters. Also das:Wird dies werden:
quelle
Ich wollte die Antwort von @ I3arnon mit einem Beweis bereichern, dass sie zur Kompilierungszeit ausgewertet wird.
Nehmen wir an, ich möchte den Namen einer Variablen in der Konsole mit dem
nameof
Operator drucken :Wenn Sie die generierte MSIL auschecken, werden Sie feststellen, dass sie einer Zeichenfolgendeklaration entspricht, da ein Objektverweis auf eine Zeichenfolge mit dem
ldstr
Operator auf den Stapel verschoben wird:Sie werden feststellen, dass das Deklarieren der Vorname-Zeichenfolge und die Verwendung des
nameof
Operators denselben Code in MSIL generiert. Dies bedeutet, dass diesnameof
genauso effizient ist wie das Deklarieren einer Zeichenfolgenvariablen.quelle
nameof
Operator und nicht um eine einfache fest codierte Zeichenfolge handelt?