6.0版获得了nameof的新功能,但我不能理解它的目的,因为它只是接受变量名并在编译时将其更改为字符串。

我认为它在使用<T>时可能有一些目的,但当我尝试命名(T)时,它只是打印我一个T而不是使用的类型。

知道目的吗?


当前回答

如果您想重用属性名,例如根据属性名抛出异常,或者处理PropertyChanged事件,该怎么办呢?在许多情况下,您都希望拥有属性的名称。

举个例子:

switch (e.PropertyName)
{
    case nameof(SomeProperty):
    { break; }

    // opposed to
    case "SomeOtherProperty":
    { break; }
}

在第一种情况下,如果不同时更改属性定义和nameof(SomeProperty)表达式,则重命名SomeProperty将导致编译错误。在第二种情况下,重命名SomeOtherProperty或更改“SomeOtherProperty”字符串将导致无声地破坏运行时行为,在构建时没有错误或警告。

这是一种非常有用的方法,可以保持代码的编译和(在某种程度上)没有错误。

(Eric Lippert写了一篇很好的文章,为什么infoof没有入选,而nameof却入选了)

其他回答

你的问题已经表达了目的。您必须看到,这对于记录日志或抛出异常可能很有用。

例如:

public void DoStuff(object input)
{
    if (input == null)
    {
        throw new ArgumentNullException(nameof(input));
    }
}

这很好。如果我更改了变量的名称,代码将中断,而不是返回带有错误消息的异常。


当然,用途并不局限于这种简单的情况。只要对变量或属性的名称进行编码是有用的,就可以使用nameof。

当您考虑各种绑定和反射情况时,其用途是多方面的。这是一种将运行时错误带到编译时的极好方法。

我能想到的最常见的用例是使用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的属性/参数。

请注意,有些框架使用一些反射魔法来获取属性的名称,但现在我们不再需要nameof this了。

最常见的用法是在输入验证中,例如

//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你就不用担心了。

参见:nameof (c#和Visual Basic参考)

nameof关键字的用法之一是在wpf中以编程方式设置Binding。

要设置绑定,你必须设置路径字符串和nameof关键字,可以使用重构选项。

例如,如果你在你的UserControl中有IsEnable依赖属性,你想把它绑定到你的UserControl中某些复选框的IsEnable上,你可以使用这两个代码:

CheckBox chk = new CheckBox();
Binding bnd = new Binding ("IsEnable") { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);

and

CheckBox chk = new CheckBox();
Binding bnd = new Binding (nameof (IsEnable)) { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);

很明显,第一个代码不能重构,但第二个代码……

MSDN文章列出了MVC路由(这个例子让我真正理解了这个概念)。(格式化的)描述段落如下:

当报告代码中的错误时, 连接模型-视图-控制器(MVC)链接, 触发属性改变事件,等等, 你经常想要 捕获方法的字符串名称。使用nameof有助于保存代码 在重命名定义时有效。 在你必须使用字符串字面量之前 来引用定义,这在重命名代码元素时是很脆弱的 因为工具不知道检查这些字符串字面量。

公认的/评分最高的答案已经给出了几个很好的具体例子。