6.0版获得了nameof的新功能,但我不能理解它的目的,因为它只是接受变量名并在编译时将其更改为字符串。
我认为它在使用<T>时可能有一些目的,但当我尝试命名(T)时,它只是打印我一个T而不是使用的类型。
知道目的吗?
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 },
}
}
其他回答
最常见的用法是在输入验证中,例如
//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参考)
它在使用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)}" })
}
}
如果你使用重构工具重命名你的属性,你的验证不会被破坏。
如果您想重用属性名,例如根据属性名抛出异常,或者处理PropertyChanged事件,该怎么办呢?在许多情况下,您都希望拥有属性的名称。
举个例子:
switch (e.PropertyName)
{
case nameof(SomeProperty):
{ break; }
// opposed to
case "SomeOtherProperty":
{ break; }
}
在第一种情况下,如果不同时更改属性定义和nameof(SomeProperty)表达式,则重命名SomeProperty将导致编译错误。在第二种情况下,重命名SomeOtherProperty或更改“SomeOtherProperty”字符串将导致无声地破坏运行时行为,在构建时没有错误或警告。
这是一种非常有用的方法,可以保持代码的编译和(在某种程度上)没有错误。
(Eric Lippert写了一篇很好的文章,为什么infoof没有入选,而nameof却入选了)
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);
很明显,第一个代码不能重构,但第二个代码……
操作符名称的目的是提供工件的源名称。
通常源名称与元数据名称相同:
public void M(string p)
{
if (p == null)
{
throw new ArgumentNullException(nameof(p));
}
...
}
public int P
{
get
{
return p;
}
set
{
p = value;
NotifyPropertyChanged(nameof(P));
}
}
但情况并非总是如此:
using i = System.Int32;
...
Console.WriteLine(nameof(i)); // prints "i"
Or:
public static string Extension<T>(this T t)
{
return nameof(T); returns "T"
}
我给它的一个用途是命名资源:
[Display(
ResourceType = typeof(Resources),
Name = nameof(Resources.Title_Name),
ShortName = nameof(Resources.Title_ShortName),
Description = nameof(Resources.Title_Description),
Prompt = nameof(Resources.Title_Prompt))]
事实上,在这种情况下,我甚至不需要生成的属性来访问资源,但是现在我有一个编译时检查资源是否存在。