Roslyn to nowa platforma kompilatora. Jest używany tylko w czasie kompilacji.
Paulo Morgado
2
@PauloMorgado to nieprawda, możesz używać Rosyln w czasie wykonywania, aby robić różne rzeczy. Na przykład zbudowanie edytora kodu na żywo lub użycie parsowania Rosyln do robienia rzeczy z drzewami lub wyrażeniami lub czymś w tym rodzaju
Chris Marisic
@ChrisMarisic takie mam wrażenie, ale nie odpowiedziałem, bo moja wiedza na ten temat jest ograniczona (stąd moje pytanie). Natknąłem się na to: scriptcs.net, który jest całkiem dobrym przykładem potęgi Roslyn i który, jak sądzę, działa w środowisku wykonawczym, ale mogę się mylić, ponieważ nie jestem o tym dobrze poinformowany.
Gigi
@ChrisMarisic, więc mówisz, że możesz użyć Roslyna do zbudowania kodu na żywo ze źródła, a nie z jednego uruchomionego pliku binarnego. I nadal używasz Roslyna do przekształcania źródeł w pliki binarne, które nie będą używać Roslyna do zmiany tych plików. Jeśli nie możesz niezauważalnie używać Roslyn w czasie wykonywania, nigdy nie możesz skompilować żadnego kodu.
Paulo Morgado
Odpowiedzi:
119
Tak. nameof()jest oceniany w czasie kompilacji. Patrząc na najnowszą wersję specyfikacji:
Nazwa wyrażenia jest stałą. We wszystkich przypadkach nameof (...) jest oceniane w czasie kompilacji w celu utworzenia ciągu. Jego argument nie jest oceniany w czasie wykonywania i jest uważany za nieosiągalny kod (jednak nie emituje ostrzeżenia „nieosiągalny kod”).
Jak wspomniano w komentarzach, oznacza to, że gdy używasz nameofparametrów typu w typie ogólnym, nie spodziewaj się, że otrzymasz nazwę rzeczywistego typu dynamicznego używanego jako parametr typu, zamiast tylko nazwy parametru typu. Więc to:
Załóżmy, że chcę wydrukować nazwę zmiennej w konsoli za pomocą nameofoperatora:
var firstname ="Gigi";var varname = nameof(firstname);Console.WriteLine(varname);// Prints "firstname" to the console
Kiedy sprawdzisz wygenerowany MSIL, zobaczysz, że jest on równoważny deklaracji ciągu, ponieważ odwołanie do obiektu do ciągu jest wypychane na stos za pomocą ldstroperatora:
Zauważysz, że zadeklarowanie ciągu firstname i użycie nameofoperatora generuje ten sam kod w MSIL, co oznacza, że nameofjest tak samo wydajne, jak deklarowanie zmiennej łańcuchowej.
Jeśli MSIL jest dekompilowany do kodu źródłowego, jak łatwo będzie dekompilatorowi rozpoznać, że był to nameofoperator, a nie zwykły ciąg znaków zakodowanych na stałe?
ADTC
11
To dobre pytanie! możesz wysłać to jako nowe pytanie do SO, jeśli chcesz uzyskać szczegółowe wyjaśnienie :) .. jednak krótka odpowiedź jest taka, że dekompilator nie będzie w stanie dowiedzieć się, że był to operator nameof, ale zamiast tego użyje literału ciągu . Sprawdziłem, że tak jest w przypadku ILSpy i Reflector.
Faris Zacina
2
@ADTC: Skoro nameof jest w pełni zastępowana przez load-a-string-on-the-stack, jak dekompilator mógłby nawet próbować odgadnąć, że to nameof, a nie prosty parametr stały?
quetzalcoatl
2
To jest interesujące. Być może dekompilator mógłby sprawdzić ciąg znaków w bieżącym kontekście (nazwa metody / właściwości / itp., W którym się znajdujesz). Mimo to nie ma sposobu, aby był w 100% niezawodny - w końcu mogłeś użyć zakodowanego na stałe ciągu.
Gigi
2
Chociaż zgadzam się, że nie możesz wiedzieć, czy to nameof po kompilacji, nie widzę żadnej wskazówki, że ILSpy lub Reflector obsługują jeszcze C # 6. Jeśli tak jest, nie możesz tego przetestować @TheMinister
Odpowiedzi:
Tak.
nameof()
jest oceniany w czasie kompilacji. Patrząc na najnowszą wersję specyfikacji:Od operatora nameof - v5
Możesz to zobaczyć w tym przykładzie TryRoslyn, gdzie:
Jest kompilowany i dekompilowany do tego:
Jego odpowiednik w czasie wykonywania to:
Jak wspomniano w komentarzach, oznacza to, że gdy używasz
nameof
parametrów typu w typie ogólnym, nie spodziewaj się, że otrzymasz nazwę rzeczywistego typu dynamicznego używanego jako parametr typu, zamiast tylko nazwy parametru typu. Więc to:Stanie się tym:
źródło
Chciałem wzbogacić odpowiedź udzieloną przez @ I3arnon o dowód, że jest oceniana w czasie kompilacji.
Załóżmy, że chcę wydrukować nazwę zmiennej w konsoli za pomocą
nameof
operatora:Kiedy sprawdzisz wygenerowany MSIL, zobaczysz, że jest on równoważny deklaracji ciągu, ponieważ odwołanie do obiektu do ciągu jest wypychane na stos za pomocą
ldstr
operatora:Zauważysz, że zadeklarowanie ciągu firstname i użycie
nameof
operatora generuje ten sam kod w MSIL, co oznacza, żenameof
jest tak samo wydajne, jak deklarowanie zmiennej łańcuchowej.źródło
nameof
operator, a nie zwykły ciąg znaków zakodowanych na stałe?