Pat*_*man 299
如果要重用属性名称,例如基于属性名称抛出异常或处理PropertyChanged事件,则会发生什么情况.在许多情况下,您可能希望拥有该属性的名称.
举个例子:
switch (e.PropertyName)
{
    case nameof(SomeProperty):
    { break; }
    // opposed to
    case "SomeOtherProperty":
    { break; }
}
在第一种情况下,重命名SomeProperty也会更改属性的名称,否则将破坏编译.最后一个案例没有.
这是一种非常有用的方法来保持代码编译和无错误(排序).
(来自Eric Lippert的一篇非常好的文章为什么infoof没有成功,同时nameof呢)
Kei*_*ith 166
它ArgumentException对它及其衍生物非常有用:
public string DoSomething(string input) 
{
    if(input == null) 
    {
        throw new ArgumentNullException(nameof(input));
    }
    ...
现在,如果有人重构input参数的名称,异常也将保持最新.
它在以前必须使用反射来获取属性或参数名称的某些地方也很有用.
在您的示例中nameof(T)获取type参数的名称 - 这也是有用的:
throw new ArgumentException(nameof(T), $"Type {typeof(T)} does not support this method.");
nameof枚举的另一个用途是 - 通常如果你想要你使用的枚举的字符串名称.ToString():
enum MyEnum { ... FooBar = 7 ... }
Console.WriteLine(MyEnum.FooBar.ToString());
> "FooBar"
这实际上相对较慢,因为.Net保存枚举值(即7)并在运行时查找名称.
而是使用nameof:
Console.WriteLine(nameof(MyEnum.FooBar))
> "FooBar"
现在.Net在编译时用字符串替换枚举名称.
还有一个用途是用于INotifyPropertyChanged记录和记录 - 在这两种情况下,您希望将要调用的成员的名称传递给另一个方法:
// Property with notify of change
public int Foo
{
    get { return this.foo; }
    set
    {
        this.foo = value;
        PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.Foo));
    }
}
要么...
// Write a log, audit or trace for the method called
void DoSomething(... params ...)
{
    Log(nameof(DoSomething), "Message....");
}
sat*_*esh 25
另一个使用nameofC#6.0功能的用例 - 考虑像Dapper这样的库,这使得DB检索变得更加容易.虽然这是一个很棒的库,但您需要在查询中对属性/字段名称进行硬编码.这意味着如果您决定重命名属性/字段,则很有可能忘记更新查询以使用新字段名称.使用字符串插值和nameof功能,代码变得更容易维护和类型安全.
从链接中给出的示例
没有名字
var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });
名字的
var dog = connection.Query<Dog>($"select {nameof(Dog.Age)} = @Age, {nameof(Dog.Id)} = @Id", new { Age = (int?)null, Id = guid });
Jod*_*ell 21
你的问题已经表达了目的.您必须看到这对于记录或抛出异常可能很有用.
例如.
public void DoStuff(object input)
{
    if (input == null)
    {
        throw new ArgumentNullException(nameof(input));
    }
}
这很好,如果我更改代码将中断的变量名称或返回带有错误消息的异常.
当然,用途不限于这种简单的情况.nameof只要对变量或属性的名称进行编码就可以使用.
当您考虑各种绑定和反射情况时,用途是多方面的.它是将运行时错误带入编译时间的绝佳方法.
Roy*_* T. 14
我能想到的最常见的用例是使用INotifyPropertyChanged界面时.(基本上与WPF和绑定相关的所有内容都使用此接口)
看看这个例子:
public class Model : INotifyPropertyChanged
{
    // From the INotifyPropertyChanged interface
    public event PropertyChangedEventHandler PropertyChanged;
    private string foo;
    public String Foo
    {
        get { return this.foo; }
        set
        {
            this.foo = value;
            // Old code:
            PropertyChanged(this, new PropertyChangedEventArgs("Foo"));
            // New Code:
            PropertyChanged(this, new PropertyChangedEventArgs(nameof(Foo)));           
        }
    }
}
正如您在旧方式中所看到的,我们必须传递一个字符串来指示哪个属性已更改.随着nameof我们可以直接使用属性的名称.这似乎不是什么大不了的事.但想象当有人改变房产名称时会发生什么Foo.使用字符串时,绑定将停止工作,但编译器不会警告您.使用nameof时,您会收到编译器错误,指出没有名称的属性/参数Foo.
请注意,某些框架使用一些反射魔法来获取属性的名称,但现在我们已经不再需要这个名称了.
最常见的用法是输入验证,例如
//Currently
void Foo(string par) {
   if (par == null) throw new ArgumentNullException("par");
}
//C# 6 nameof
void Foo(string par) {
   if (par == null) throw new ArgumentNullException(nameof(par));
}
在第一种情况下,如果重构方法更改par参数的名称,您可能会忘记在ArgumentNullException中更改它.有了这个名字你就不用担心了.
另请参见:nameof(C#和Visual Basic参考)
在ASP.NET MVC的核心项目使用nameof的AccountController.cs,并ManageController.cs与RedirectToAction方法在控制器中引用的动作.
例:
return RedirectToAction(nameof(HomeController.Index), "Home");
这意味着:
return RedirectToAction("Index", "Home");
并且take将用户带到'Home'控制器中的'Index'动作,即/Home/Index.
正如其他人已经指出的那样,nameof运算符确实插入了源代码中给出元素的名称.
我想补充说,这在重构方面是一个非常好的主意,因为它使这个字符串重构安全.以前,我使用静态方法将反射用于相同目的,但这会影响运行时性能.该nameof运营商还没有运行时性能的影响; 它在编译时完成它的工作.如果您查看MSIL代码,您会发现嵌入的字符串.请参阅以下方法及其反汇编代码.
static void Main(string[] args)
{
    Console.WriteLine(nameof(args));
    Console.WriteLine("regular text");
}
// striped nops from the listing
IL_0001 ldstr args
IL_0006 call System.Void System.Console::WriteLine(System.String)
IL_000C ldstr regular text
IL_0011 call System.Void System.Console::WriteLine(System.String)
IL_0017 ret
但是,如果您计划对软件进行模糊处理,那么这可能是一个缺点.混淆后,嵌入的字符串可能不再与元素的名称匹配.依赖于此文本的机制将会中断.示例包括但不限于:Reflection,NotifyPropertyChanged ......
在运行时确定名称会降低某些性能,但对于混淆是安全的.如果既不需要也不计划混淆,我建议使用nameof运算符.
考虑一下你在代码中使用一个变量,并且需要获取变量的名称,然后打印它,你应该使用它
int myVar = 10;
print("myVar" + " value is " + myVar.toString());
然后,如果有人重构代码并使用另一个名称"myVar",他/她将不得不在代码中查看字符串值并相应地改变它.
相反,如果你有
print(nameof(myVar) + " value is " + myVar.toString());
这将有助于自动重构!