web-dev-qa-db-ja.com

nameof()はコンパイル時に評価されますか?

C#6では、 nameof() 演算子を使用して、変数または型の名前を含む文字列を取得できます。

これはコンパイル時に、または実行時にRoslyn APIを介して評価されますか?

111
Gigi

はい。 nameof()はコンパイル時に評価されます。仕様の最新バージョンを見る:

Nameof式は定数です。すべての場合において、nameof(...)はコンパイル時に評価され、文字列を生成します。その引数は実行時に評価されず、到達不能コードと見なされます(ただし、「到達不能コード」警告を発しません)。

演算子の名前-v5 から

このTryRoslynの例 でこれを見ることができます。

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

これにコンパイルされ、逆コンパイルされます:

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

同等の実行時は:

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

コメントで述べたように、それは、ジェネリック型の型パラメーターでnameofを使用する場合、型だけでなく型パラメーターとして使用される実際の動的型の名前を取得することを期待しないことを意味しますパラメータの名前。したがって、この:

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

なります これ:

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

@ I3arnonによって提供される答え を、コンパイル時に評価されるという証拠で強化したかったのです。

nameof演算子を使用して、コンソールに変数の名前を出力したいとします。

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

生成されたMSILをチェックアウトすると、文字列へのオブジェクト参照がldstr演算子を使用してスタックにプッシュされるため、文字列宣言と同等であることがわかります。

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)

Firstname文字列を宣言してnameof演算子を使用すると、MSILで同じコードが生成されます。つまり、nameofは文字列変数を宣言するのと同じくらい効率的です。

58
Faris Zacina