6.0版获得了nameof的新功能,但我不能理解它的目的,因为它只是接受变量名并在编译时将其更改为字符串。
我认为它在使用<T>时可能有一些目的,但当我尝试命名(T)时,它只是打印我一个T而不是使用的类型。
知道目的吗?
6.0版获得了nameof的新功能,但我不能理解它的目的,因为它只是接受变量名并在编译时将其更改为字符串。
我认为它在使用<T>时可能有一些目的,但当我尝试命名(T)时,它只是打印我一个T而不是使用的类型。
知道目的吗?
当前回答
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});
其他回答
我发现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参考)
它对ArgumentException及其衍生物非常有用:
public string DoSomething(string input)
{
if(input == null)
{
throw new ArgumentNullException(nameof(input));
}
...
现在,如果有人重构输入参数的名称,异常也将保持最新。
在以前必须使用反射来获取属性或参数名称的某些地方,它也很有用。
在你的例子中,nameof(T)获取类型参数的名称-这也很有用:
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....");
}
MSDN文章列出了MVC路由(这个例子让我真正理解了这个概念)。(格式化的)描述段落如下:
当报告代码中的错误时, 连接模型-视图-控制器(MVC)链接, 触发属性改变事件,等等, 你经常想要 捕获方法的字符串名称。使用nameof有助于保存代码 在重命名定义时有效。 在你必须使用字符串字面量之前 来引用定义,这在重命名代码元素时是很脆弱的 因为工具不知道检查这些字符串字面量。
公认的/评分最高的答案已经给出了几个很好的具体例子。
nameof的另一个用例是检查标签页,而不是检查索引,你可以检查标签页的Name属性,如下:
if(tabControl.SelectedTab.Name == nameof(tabSettings))
{
// Do something
}
不那么乱:)