Nameof () derleme zamanında değerlendirilir mi?


114

C # 6'da, nameof()bir değişkenin veya bir türün adını içeren bir dize almak için operatörü kullanabilirsiniz .

Bu, derleme zamanında mı yoksa bazı Roslyn API aracılığıyla çalışma zamanında mı değerlendirilir?


Roslyn, yeni derleyici platformudur. Yalnızca derleme sırasında kullanılır.
Paulo Morgado

2
@PauloMorgado bu doğru değil, bir şeyler yapmak için Rosyln'i çalışma zamanında kullanabilirsiniz. Canlı bir kod editörü oluşturmak veya ağaçlarla veya ifadelerle bir şeyler yapmak için Rosyln'in ayrıştırma öğelerini kullanmak gibi
Chris Marisic

@ChrisMarisic bu benim izlenimim, ancak konu hakkındaki bilgim sınırlı olduğu için cevap vermedim (dolayısıyla sorum). Şuna rastladım: Roslyn'in gücünün oldukça iyi bir örneği olan ve çalışma zamanıyla ilgili şeyler yaptığına inandığım scriptcs.net , ancak bu konuda pek bilgili olmadığım için yanılıyor olabilirim.
Gigi

@ChrisMarisic, yani, Roslyn'i çalışan tek bir ikili dosyadan değil, kaynaktan canlı kod oluşturmak için kullanabileceğinizi söylüyorsunuz. Ve yine de Roslyn'i bu binileri değiştirmek için Roslyn'i kullanmayacak ikili dosyalara dönüştürmek için kullanıyorsunuz. Roslyn'i çalışma zamanında kesinlikle kullanamazsanız, o zaman hiçbir kodu derleyemezsiniz.
Paulo Morgado

Yanıtlar:


119

Evet. nameof()derleme zamanında değerlendirilir. Teknik özelliklerin en son sürümüne bakıldığında:

İfadenin adı sabittir. Her durumda, nameof (...), bir dizge oluşturmak için derleme zamanında değerlendirilir . Argümanı çalışma zamanında değerlendirilmez ve erişilemez kod olarak kabul edilir (ancak bir "erişilemez kod" uyarısı vermez).

Gönderen NameOf operatörü - v5

Bunu bu TryRoslyn örneğiyle görebilirsiniz, burada:

public class Foo
{
    public void Bar()
    {
        Console.WriteLine(nameof(Foo));
    }
}

Şu şekilde derlenir ve derlenir:

public class Foo
{
    public void Bar()
    {
        Console.WriteLine("Foo");
    }
}

Çalışma zamanı eşdeğeri:

public class Foo
{
    public void Bar()
    {
        Console.WriteLine(typeof(Foo).Name);
    }
}

Yorumlarda belirtildiği gibi, bu, nameofgenel bir türdeki tür parametrelerinde kullandığınızda, yalnızca tür parametresinin adı yerine bir tür parametresi olarak kullanılan gerçek dinamik türün adını almayı beklemediğiniz anlamına gelir . Yani bu:

public class Foo
{
    public void Bar<T>()
    {
        Console.WriteLine(nameof(T));
    }
}

Hale gelecek bu:

public class Foo
{
    public void Bar<T>()
    {
        Console.WriteLine("T");
    }
}

Burada "derleme zamanı" nedir? MSIL'e derleme mi yoksa yerel koda derleme mi?
user541686

6
@Mehrdad C # derleyicisi IL üretir.
i3arnon

3
Hızlı soru, bir anahtar durumunda nameof kullanabilir miyim?
Yazım

2
@Spell Yes
i3arnon

58

@ I3arnon tarafından sağlanan yanıtı , derleme zamanında değerlendirildiğine dair bir kanıtla zenginleştirmek istedim .

nameofOperatörü kullanarak Konsoldaki bir değişkenin adını yazdırmak istediğimi varsayalım :

 var firstname = "Gigi";
 var varname = nameof(firstname);
 Console.WriteLine(varname); // Prints "firstname" to the console

Oluşturulan MSIL'yi teslim aldığınızda, bunun bir dize bildirimine eşdeğer olduğunu göreceksiniz çünkü bir dizeye bir nesne başvurusu, ldstrişleci kullanılarak yığına itilir :

IL_0001: ldstr "Gigi"
IL_0006: stloc.0
IL_0007: ldstr "firstname"
IL_000c: stloc.1
IL_000d: ldloc.1
IL_000e: call void [mscorlib]System.Console::WriteLine(string)

İlk ad dizesini bildirmenin ve nameofoperatörü kullanmanın MSIL'de aynı kodu ürettiğini fark edeceksiniz , bu nameof, bir dize değişkeni bildirmek kadar verimli olduğu anlamına gelir .


4
MSIL kaynak koduna dönüştürülürse, derleyicinin nameofdüz bir sabit kodlu dizge değil de bir operatör olduğunu anlaması ne kadar kolay olur ?
ADTC

11
Bu iyi bir soru! Eğer ayrıntılı bir açıklama almak istiyorsanız bunu SO'da yeni bir soru olarak gönderebilirsiniz :) .. ancak kısa cevap, derleyicinin bunun bir operatör adı olduğunu anlayamayacağı, bunun yerine bir dize değişmezi kullanacağıdır. . ILSpy ve Reflector'da durumun böyle olduğunu doğruladım.
Faris Zacina

2
@ADTC: nameof tamamen yığına bir dizge yükle ile değiştirildiğinden, kod çözücü nasıl basit bir sabit parametre değil de bir nameof olduğunu tahmin etmeye bile çalışabilir?
quetzalcoatl

2
Bu ilginç. Belki de derleyici, dizeyi geçerli bağlama göre kontrol edebilir (içinde bulunduğunuz yöntem / özellik / vb. Adı). Yine de,% 100 güvenilir olmasının bir yolu yoktur - sonuçta sabit kodlanmış bir dize kullanmış olabilirsiniz.
Gigi

2
Derledikten sonra bunun bir adı olup olmadığını bilemeyeceğinizi kabul etsem de, ILSpy veya Reflector'ın C # 6'yı desteklediğine dair herhangi bir belirti görmüyorum. Durum buysa, test edemezsiniz @TheMinister
Millie Smith
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.