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

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

知道目的吗?


当前回答

我发现nameof增加了应用程序中非常长和复杂的SQL语句的可读性。它使变量从字符串的海洋中脱颖而出,并消除了确定变量在SQL语句中的使用位置的工作。

public bool IsFooAFoo(string foo, string bar)
{
    var aVeryLongAndComplexQuery = $@"SELECT yada, yada
    -- long query in here
    WHERE fooColumn = @{nameof(foo)}
    AND barColumn = @{nameof(bar)}
    -- long query here";


    SqlParameter[] parameters = {
        new SqlParameter(nameof(foo), SqlDBType.VarChar, 10){ Value = foo },
        new SqlParameter(nameof(bar), SqlDBType.VarChar, 10){ Value = bar },
    }
}

其他回答

我发现nameof增加了应用程序中非常长和复杂的SQL语句的可读性。它使变量从字符串的海洋中脱颖而出,并消除了确定变量在SQL语句中的使用位置的工作。

public bool IsFooAFoo(string foo, string bar)
{
    var aVeryLongAndComplexQuery = $@"SELECT yada, yada
    -- long query in here
    WHERE fooColumn = @{nameof(foo)}
    AND barColumn = @{nameof(bar)}
    -- long query here";


    SqlParameter[] parameters = {
        new SqlParameter(nameof(foo), SqlDBType.VarChar, 10){ Value = foo },
        new SqlParameter(nameof(bar), SqlDBType.VarChar, 10){ Value = bar },
    }
}

它在使用ASP时具有一定的优势。净MVC。当你使用HTML helper在视图中构建一些控件时,它使用HTML输入的name属性中的属性名:

@Html.TextBoxFor(m => m.CanBeRenamed)

它是这样的:

<input type="text" name="CanBeRenamed" />

所以现在,如果你需要在validate方法中验证你的属性,你可以这样做:

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
  if (IsNotValid(CanBeRenamed)) {
    yield return new ValidationResult(
      $"Property {nameof(CanBeRenamed)} is not valid",
      new [] { $"{nameof(CanBeRenamed)}" })
  }
}

如果你使用重构工具重命名你的属性,你的验证不会被破坏。

正如其他人已经指出的那样,操作符的名称确实插入了源代码中给出的元素名称。

我想补充一点,这在重构方面是一个非常好的想法,因为它使得字符串重构是安全的。以前,我使用了一个静态方法,它利用反射来达到同样的目的,但这对运行时性能有影响。操作符的名称对运行时性能没有影响;它在编译时完成它的工作。如果查看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…

在运行时确定名称会损失一些性能,但对于混淆是安全的。如果混淆既不需要也不计划,我建议使用操作符的名称。

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

例如:

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

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


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

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

nameof的目的是重构。例如,当你在代码中其他地方通过nameof引用一个类的名字时,你会得到一个编译错误,这是你想要的。如果你没有使用nameof,只有一个普通的字符串作为引用,你必须全文搜索类的名称才能更改它。那是一种痛苦。有了nameof,您就可以轻松地在IDE中自动构建和获取所有需要更改的用例。