最重要的是nameof不会影响性能!

nameof有什么用?主要用解决 类成员名做参数替代成员们的字符串做参数,如下:

using  System;
namespace csharp6
{
internal class Program
{
private static void Main(string[] args)
{
if (args==null)
{
throw new ArgumentNullException("args");//旧的写法 变量名的字符串做参数 //throw new ArgumentNullException(nameOf(args));//新的写法 避免了args变量名更改后,忘记更改字符串"args",因为字符串编译器是不错提示错误的 } } } }

这样非常有利于后期项目维护,比如我们在使用MVC开发时候,后端返回到某个视图,我们平时喜欢写字符串的形式,如果项目越来越大,后期突然哪个控制器或者动作不用了,使用字符串的形式维护起来就非常麻烦,用nameof就可以很好的解决,最重要的是不会影响性能!

nameof 运算符

nameof是C#6新增的一个关键字运算符,主要作用是方便获取类型、成员和变量的简单字符串名称(非完全限定名),意义在于避免我们在代码中写下固定的一些字符串,这些固定的字符串在后续维护代码时是一个很繁琐的事情。比如上面的代码改写后:

using  System;
namespace csharp6
{
internal class Program
{
private static void Main(string[] args)
{
if (args==null)
{
throw new ArgumentNullException(nameof(args));
}
}
}
}

我们把固定的 "args" 替换成等价的 nameof(args) 。按照惯例,贴出来两种方式的代码的IL。

"args"方式的IL代码

.method private hidebysig static void  Main(string[] args) cil managed
{
.entrypoint
// Code size 22 (0x16)
.maxstack 2
.locals init ([0] bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldnull
IL_0003: ceq
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: brfalse.s IL_0015
IL_0009: nop
IL_000a: ldstr "args"
IL_000f: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)
IL_0014: throw
IL_0015: ret
} // end of method Program::Main

nameof(args)方式的IL代码:

.method private hidebysig static void  Main(string[] args) cil managed
{
.entrypoint
// Code size 22 (0x16)
.maxstack 2
.locals init ([0] bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldnull
IL_0003: ceq
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: brfalse.s IL_0015
IL_0009: nop
IL_000a: ldstr "args"
IL_000f: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string)
IL_0014: throw
IL_0015: ret
} // end of method Program::Main

一样一样的,我是没看出来有任何的差异,,,so,这个运算符也是一个编译器层面提供的语法糖,编译后就没有nameof的影子了。

3. nameof 注意事项

nameof可以用于获取具名表达式的当前名字简单字符串表示(非完全限定名)。注意当前名字这个限定,比如下面这个例子,你觉得会输出什么结果?

using static System.Console;
using CC = System.ConsoleColor; namespace csharp6
{
internal class Program
{
private static void Main()
{
WriteLine(nameof(CC));//CC
WriteLine(nameof(System.ConsoleColor));//ConsoleColor
}
}
}

第一个语句输出"CC",因为它是当前的名字,虽然是指向System.ConsoleColor枚举的别名,但是由于CC是当前的名字,那么nameof运算符的结果就是"CC"。

第二个语句输出了"ConsoleColor",因为它是System.ConsoleColor的简单字符串表示,而非取得它的完全限定名,如果想取得"System.ConsoleColor",那么请使用 typeof(System.ConsoleColor).FullName 。再比如微软给的例子: nameof(person.Address.ZipCode) ,结果是"ZipCode"。

以上内容来自:

https://www.cnblogs.com/lsgsanxiao/p/10977335.html

以前我们使用的是这样的:

// 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()了。


 

如果要重用属性名称,例如在基于属性名称引发异常或处理 PropertyChanged 事件时,该怎么办? 在很多情况下,您都希望使用属性名称。

举个例子:

switch (e.PropertyName)
{
case nameof(SomeProperty):
{ break; } // opposed to
case "SomeOtherProperty":
{ break; }
}

在第一种情况下,重命名 SomeProperty 也将更改属性的名称,否则将中断编译。 最后一种情况没有。

这是保持代码编译和消除错误(排序)的一种非常有用的方法。

Eric Lippert的一篇非常不错的文章, 为什么 infoof 没能做到,而 nameof 却做到了)


 

对于 ArgumentException 及其派生类确实非常有用:

public string DoSomething(string input)
{
if(input == null)
{
throw new ArgumentNullException(nameof(input));
}
...

现在,如果有人重构 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....");
}

 

我能想到的最常见的用例是使用 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,它不再是必需的


 

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

//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参考)


 

考虑到您在代码中使用了变量,并且需要获取变量的名称并可以说将其打印出来,因此您必须使用

int myVar = 10;
print("myVar" + " value is " + myVar.toString());

然后如果有人重构代码并为“ myVar”使用另一个名称,则他/她将必须注意代码中的字符串值并相应地对其进行处理。

相反,如果您有

print(nameof(myVar) + " value is " + myVar.toString());

这将有助于自动重构!


 

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

要设置 Binding 您必须使用字符串和 nameof 关键字设置 Path ,可以使用Refactor选项。

例如,如果您在 UserControl 具有 IsEnable 依赖项属性,并且要将其绑定到 UserControl 中某些 CheckBox IsEnable ,则可以使用以下两个代码:

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

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

很明显,第一个代码无法重构,而第二个代码可以重构。


 

nameof 运算符的目的是提供工件的源名称。

通常,源名称与元数据名称相同:

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"

要么:

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))]

事实是,在这种情况下,我什至不需要生成的属性来访问资源,但是现在有了编译时检查资源是否存在。


 

C#6.0的 nameof 功能变得很方便的另一个用例 -考虑像 Dapper 这样的库,它使DB检索更加容易。 尽管这是一个很棒的库,但是您需要在查询中对属性/字段名称进行硬编码。 这意味着如果您决定重命名属性/字段,则很可能会忘记更新查询以使用新的字段名。 使用字符串插值和 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 });

以上内容来自: https://code-examples.net/zh-CN/q/1e3a41c

【c# 操作符】- nameof用法的更多相关文章

  1. C#nameof用法

    1.实现代码 using System; namespace NameofUsage { /// <summary> /// C# nameof用法 /// </summary> ...

  2. 数据仓库之抽取数据:openrowset函数带bulk操作符的用法

    原文:数据仓库之抽取数据:openrowset函数带bulk操作符的用法 在做数据仓库时,最重要的就是ETL的开发,而在ETL开发中的第一步,就是要从原OLTP系统中抽取数据到过渡区中,再对这个过渡区 ...

  3. java中操作符的用法

    5.操作符    public class Test{   public static void main(String[] args){     int i, k;     i = 10; /*下面 ...

  4. C++ sizeof 操作符的用法总结

    在VC中,sizeof有着许多的用法,而且很容易引起一些错误.下面根据sizeof后面的参数对sizeof的用法做个总结. A.参数为数据类型或者为一般变量: 例如sizeof(int),sizeof ...

  5. RxJava(一) create操作符的用法和源码分析

    欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/51524470 本文出自:[余志强的博客] 1 create操作符的基 ...

  6. Javascript之in操作符的用法

    in操作符是js里面常用的一个操作符,下面是其几个常用的功能: 1.配合for语句循环遍历/迭代数组中的元素 2.配合for语句循环遍历/迭代集合中的属性 3.判断对象是否是数组的元素 4.判断对象是 ...

  7. Mybatis 动态SQL注解 in操作符的用法

    在SQL语法中如果我们想使用in的话直接可以像如下一样使用: ,,) ; ,,) ; 但是如果在MyBatis中的使用 in 操作符,像下面这样写的话,肯定会报错: @Update("upd ...

  8. RxJava(四) concatMap操作符用法详解

    欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/51533282 本文出自:[余志强的博客] concatMap操作符的 ...

  9. RxJava(三) flatMap操作符用法详解

    欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/51532776 本文出自:[余志强的博客] flatMap操作符的作用 ...

随机推荐

  1. Python webargs 模块

    一.安装 python3 -m pip install webargs 文档 二.基础特性 # encoding=utf-8 from flask import Flask from webargs ...

  2. 羽夏看Win系统内核——进程线程篇

    写在前面   此系列是本人一个字一个字码出来的,包括示例和实验截图.由于系统内核的复杂性,故可能有错误或者不全面的地方,如有错误,欢迎批评指正,本教程将会长期更新. 如有好的建议,欢迎反馈.码字不易, ...

  3. TeXstudio在右边显示预览

    打开预览界面后: 点击查看(View) 选择最后一个:窗口/内嵌(Windowed/Embedded) 就可以了

  4. gin框架中集成casbin-权限管理

    概念 权限管理几乎是每个系统或者服务都会直接或者间接涉及的部分. 权限管理保障了资源(大部分时候就是数据)的安全, 权限管理一般都是和业务强关联, 每当有新的业务或者业务变化时, 不能将精力完全放在业 ...

  5. Edge 91以上554、10080出现ERR_UNSAFE_PORT解决办法

    解决办法 在注册表下面这个路径新建一个键值名为1的,输入10080(或554),重启浏览器,即可解决问题. 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Micro ...

  6. el表达式中的${param}用法

    el表达式中的${param}? 1. 2. ${param.name} 等价于 request.getParamter("name"),这两种方法一般用于服务器从页面或者客户端获 ...

  7. NumPy 秘籍中文第二版·翻译完成

    原文:NumPy Cookbook - Second Edition 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远. 在线阅读 Apache ...

  8. Mysql Json函数总览 (一)

    JSON函数相关文章均来自官网,此处仅做记录,以便以后查询方便. https://dev.mysql.com/doc/refman/5.7/en/json-functions.html JSON函数参 ...

  9. Java注解和注解处理器使用方法

    原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11492274.html 准备材料: 实体类: PrintDemo 注解类: PrintName ...

  10. Redis 学习笔记(五)高可用之主从模式

    上一节提到了 Redis 的持久性,也就是在服务器实例宕机或故障时,拥有再恢复的能力.但是在这个服务器实例宕机恢复期间,是无法接受新的数据请求.对于整体服务而言这是无法容忍的,因此我们可以使用多个服务 ...