Roslyn adalah platform kompilator baru. Ini hanya digunakan pada waktu kompilasi.
Paulo Morgado
2
@PauloMorgado itu tidak benar, Anda dapat menggunakan Rosyln pada saat berjalan untuk melakukan sesuatu. Seperti membangun editor kode langsung atau menggunakan penguraian Rosyln untuk melakukan sesuatu dengan pohon atau ekspresi atau sesuatu
Chris Marisic
@ChrisMarisic itu kesan saya, tapi saya tidak merespon karena pengetahuan saya tentang topik terbatas (karena itu pertanyaan saya). Saya menemukan ini: scriptcs.net yang merupakan contoh yang cukup bagus dari kekuatan Roslyn, dan yang saya yakini melakukan hal-hal runtime, tetapi saya bisa saja salah karena saya tidak cukup mendapat informasi tentangnya.
Gigi
@ChrisMarisic, jadi, apa yang Anda katakan adalah bahwa Anda dapat menggunakan Roslyn untuk membuat kode langsung dari sumber, bukan dari satu biner yang sedang berjalan. Dan Anda masih menggunakan Roslyn untuk mengubah source menjadi binari yang tidak akan menggunakan Roslyn untuk mengubah binries tersebut. Jika Anda tidak dapat menggunakan Roslyn secara permanen saat runtime, maka Anda tidak akan pernah dapat mengkompilasi kode apa pun.
Paulo Morgado
Jawaban:
119
Iya. nameof()dievaluasi pada waktu kompilasi. Melihat versi terbaru dari spesifikasi:
Nama ekspresi adalah konstanta. Dalam semua kasus, nameof (...) dievaluasi pada waktu kompilasi untuk menghasilkan string. Argumennya tidak dievaluasi pada waktu proses, dan dianggap sebagai kode yang tidak dapat dijangkau (namun tidak mengeluarkan peringatan "kode tidak dapat dijangkau").
Seperti yang disebutkan dalam komentar, itu berarti bahwa ketika Anda menggunakan nameofparameter tipe dalam tipe generik, jangan berharap untuk mendapatkan nama tipe dinamis aktual yang digunakan sebagai parameter tipe alih-alih hanya nama parameter tipe. Jadi ini:
Mari kita asumsikan saya ingin mencetak nama variabel di Konsol menggunakan nameofoperator:
var firstname ="Gigi";var varname = nameof(firstname);Console.WriteLine(varname);// Prints "firstname" to the console
Ketika Anda memeriksa MSIL yang dihasilkan, Anda akan melihat bahwa itu setara dengan deklarasi string karena referensi objek ke string didorong ke tumpukan menggunakan ldstroperator:
Anda akan melihat bahwa mendeklarasikan string nama depan dan menggunakan nameofoperator menghasilkan kode yang sama di MSIL, yang artinya nameofseefisien mendeklarasikan variabel string.
Jika MSIL didekompilasi menjadi kode sumber, seberapa mudah bagi decompiler untuk mengenalinya sebagai nameofoperator, bukan string hardcode biasa?
ADTC
11
Itu pertanyaan yang bagus! Anda dapat mempostingnya sebagai pertanyaan baru di SO jika Anda ingin mendapatkan penjelasan rinci :) .. namun jawaban singkatnya adalah bahwa decompiler tidak akan dapat mengetahui itu adalah nama operator, tetapi akan menggunakan string literal sebagai gantinya . Saya telah memverifikasi bahwa kasus dengan ILSpy dan Reflector.
Faris Zacina
2
@ ADTC: Karena nameof sepenuhnya diganti dengan load-a-string-into-the-stack, bagaimana mungkin decompiler mencoba menebak bahwa itu adalah nameof, dan bukan parameter konstan sederhana?
quetzalcoatl
2
Itu menarik. Mungkin decompiler dapat memeriksa string terhadap konteks saat ini (nama metode / properti / dll tempat Anda berada). Namun, tidak mungkin itu 100% dapat diandalkan - Anda mungkin telah menggunakan string hardcode.
Gigi
2
Meskipun saya setuju bahwa Anda tidak dapat mengetahui apakah itu nameof setelah kompilasi, saya tidak melihat indikasi bahwa ILSpy atau Reflector mendukung C # 6. Jika itu masalahnya, Anda tidak dapat mengujinya @TheMinister
Jawaban:
Iya.
nameof()
dievaluasi pada waktu kompilasi. Melihat versi terbaru dari spesifikasi:Dari nameof operator - v5
Anda dapat melihatnya dengan contoh TryRoslyn ini di mana ini:
Dikompilasi dan diuraikan menjadi ini:
Yang setara dengan run-time adalah:
Seperti yang disebutkan dalam komentar, itu berarti bahwa ketika Anda menggunakan
nameof
parameter tipe dalam tipe generik, jangan berharap untuk mendapatkan nama tipe dinamis aktual yang digunakan sebagai parameter tipe alih-alih hanya nama parameter tipe. Jadi ini:Akan menjadi ini:
sumber
Saya ingin memperkaya jawaban yang diberikan oleh @ I3arnon dengan bukti bahwa jawaban itu dievaluasi pada waktu kompilasi.
Mari kita asumsikan saya ingin mencetak nama variabel di Konsol menggunakan
nameof
operator:Ketika Anda memeriksa MSIL yang dihasilkan, Anda akan melihat bahwa itu setara dengan deklarasi string karena referensi objek ke string didorong ke tumpukan menggunakan
ldstr
operator:Anda akan melihat bahwa mendeklarasikan string nama depan dan menggunakan
nameof
operator menghasilkan kode yang sama di MSIL, yang artinyanameof
seefisien mendeklarasikan variabel string.sumber
nameof
operator, bukan string hardcode biasa?