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

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

知道目的吗?


当前回答

它在使用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)}" })
  }
}

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

其他回答

之前我们使用的是这样的东西:

// Some form.
SetFieldReadOnly( () => Entity.UserName );
...
// Base form.
private void SetFieldReadOnly(Expression<Func<object>> property)
{
    var propName = GetPropNameFromExpr(property);
    SetFieldsReadOnly(propName);
}

private void SetFieldReadOnly(string propertyName)
{
    ...
}

原因-编译时安全。没有人可以默默地重命名属性并破坏代码逻辑。现在我们可以使用nameof()。

我发现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 },
    }
}

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

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

c# 6.0的nameof特性的另一个用例变得很方便——考虑像Dapper这样的库,它使数据库检索变得更容易。虽然这是一个很棒的库,但您需要在查询中硬编码属性/字段名。这意味着如果你决定重命名你的属性/字段,你很有可能会忘记更新查询来使用新的字段名。使用字符串插值和特性名称,代码变得更容易维护和类型安全。

从链接中给出的例子

没有nameof

var dog = connection.Query<Dog>(
    "select Age = @Age, Id = @Id",
    new {Age = (int?) null, Id = guid});

与nameof

var dog = connection.Query<Dog>(
    $"select {nameof(Dog.Age)} = @Age, {nameof(Dog.Id)} = @Id",
    new {Age = (int?) null, Id = guid});