nameof和typeof之间的区别

时间:2015-11-11 11:23:32

标签: c# built-in typeof c#-6.0 nameof

如果我错了,请纠正我,但做一些像

这样的事情
var typeOfName = typeof(Foo).Name;

var nameOfName = nameof(Foo);

应该给你完全相同的输出。根据此来源的一个可以理解的原因:https://msdn.microsoft.com/en-us/library/dn986596.aspx就是那个

  

“使用nameof有助于在重命名定义时保持代码有效”

如果你想把类实例作为字符串,可以做类似的事情:

var fooInstance = new Foo();
var nameOfName = nameof(fooInstance);

但是,您可以执行以下操作:

static string GetName<T>(T item) where T : class 
{
  return typeof(T).GetProperties()[0].Name;
}
var typeOfName2 = GetName(new { fooInstance });

在这两种情况下(typeofnameof)都可以进行重构,所以我没有看到任何其他原因重新发明另一个更高级别的关键字,例如nameof,以执行某些操作已经存在。他们之间是否有任何差异,我不清楚?

最后,如果有人能指出我参考资料来了解nameof的实施情况,我将不胜感激。它是否使用反射?

更新1: 取自here

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)

7 个答案:

答案 0 :(得分:23)

有两个原因:

nameof变成编译时常量。 typeof(...).Name需要一些反思。它不是过于昂贵,但在某些情况下会受到伤害。

其次,它用于除类型名称之外的其他内容。例如,参数:

void SomeMethod(int myArgument)
{
  Debug.WriteLine(nameof(myArgument));
}

您还可以获取班级成员甚至本地人的名称。不用说,这对于调试信息非常有用。它也是实现不那么脆弱的反射的方法之一,例如,解析表达式树(遗憾的是,在我使用它的项目中,我们仍然坚持使用C#5的.NET 4.0 - 它在这里和那里为我节省了一些黑客)。

为了澄清一些混淆,nameof 不是一个函数,typeof也不是。它是一个编译时运算符,并且它总是在编译时进行评估(尽管很明显,泛型移动&#34;编译时间&#34;稍微进一步)。

答案 1 :(得分:9)

使用Reflection生成字符串是可能的,但不是很优雅,并不总是可行。例如,您无法在沙盒代码中使用Reflection。而且你不能在局部变量上使用它。它很贵。

nameof运算符在编译时工作。编译器在解析代码时已经知道了名称。因此可以简单地生成字符串文字。非常快,可能更快,没有运行时限制。

答案 2 :(得分:7)

这是使用BenchmarkDotNet

的基准测试
// * Summary *

Host Process Environment Information:
BenchmarkDotNet.Core=v0.9.9.0
OS=Windows
Processor=?, ProcessorCount=8
Frequency=2740584 ticks, Resolution=364.8857 ns, Timer=TSC
CLR=CORE, Arch=64-bit ? [RyuJIT]
GC=Concurrent Workstation
dotnet cli version: 1.0.0-preview2-003133

Type=GetNameBenchmark  Mode=Throughput  LaunchCount=2
WarmupCount=10  TargetCount=200

     Method |     Median |    StdDev |
----------- |----------- |---------- |
     TypeOf | 16.0348 ns | 0.7896 ns |
     NameOf |  0.0005 ns | 0.0147 ns |

答案 3 :(得分:4)

它们之间存在一些差异,但它们主要是背后的实际原因。 示例1:

写一些像

这样的东西更优雅
switch (e.ArgumentPropertyName)
{
    case nameof(aProperty):
    break;

    case "anotherProperty":
    break;
}

尝试重构anotherProperty类型和爆炸! nameof将反映更改,"anotherProperty"将以静默方式传递,您的代码将永远不会在该case语句中执行..

示例2:

enum MetalEnum { Gold = 1,  Silver = 2, ... }

哪一个更好?

Console.WriteLine(MetalEnum.Gold.ToString()); // finds the name at runtime (slower)

Console.WriteLine(nameof(MetalEnum.Gold)); // compile time (faster)

示例3:

最后,你还记得编写像

这样的东西是多么丑陋
PropertyChanged(this, new PropertyChangedEventArgs("Foo"));

现在你可以写得如下:

PropertyChanged(this, new PropertyChangedEventArgs(nameof(Foo)));

答案 4 :(得分:2)

Typeof 会返回Type对象。它通常用作参数或变量或字段。 typeof运算符是获取Type指针的表达式的一部分。

class Program
{
    static Type _type = typeof(char); // Store Type as field.

    static void Main()
    {
    Console.WriteLine(_type); // Value type pointer
    Console.WriteLine(typeof(int)); // Value type
    Console.WriteLine(typeof(byte)); // Value type
    Console.WriteLine(typeof(Stream)); // Class type
    Console.WriteLine(typeof(TextWriter)); // Class type
    Console.WriteLine(typeof(Array)); // Class type
    Console.WriteLine(typeof(int[])); // Array reference type
    }
}

输出

System.Char
System.Int32
System.Byte
System.IO.Stream
System.IO.TextWriter
System.Array
System.Int32[]

Nameof 同时返回一个带有变量名称的字符串。它在编译时工作。它是一种特殊的编译器功能,可以简化某些程序。

int size=100;
Console.WriteLine(nameof(size));

输出:尺寸

答案 5 :(得分:2)

根据the documentation

  

用于获取变量,类型或成员的简单(非限定)字符串名称。

     

...

     

nameof 的参数必须是简单名称,限定名称,成员访问权限,具有指定成员的基本访问权限,或具有指定成员的此访问权限。参数表达式标识代码定义,但永远不会对其进行评估。

     

因为参数需要在语法上是一个表达式,所以有很多不允许列出的东西。以下值得一提的是产生错误:预定义类型(例如, int void ),可空类型(Point?),数组类型({{1 }},指针类型(Customer[,]),限定别名(Buffer*)和未绑定泛型类型(A::B),预处理符号(Dictionary<,>)和标签({ {1}})。

nameof 获取的简单名称是源名称,而不是元数据名称。

所以,这段代码:

DEBUG

将打印:

loop:

答案 6 :(得分:0)

Typeof返回Type对象。它通常用作参数或变量或字段。 typeof运算符是获取Type指针的表达式的一部分。

同时,Nameof返回一个带有变量名称的字符串。它在编译时工作。它是一种特殊的编译器功能,可以简化某些程序。