欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

C# 基础 nameof的用法 有大用 有大大用

nameof运算符先给出CSDN的官方定义:

nemeof运算符获取变量、类型或成员的名称作为字符串常量。

  1. Console.WriteLine(nameof(System.Collections.Generic));  // output: Generic
  2. Console.WriteLine(nameof(List<int>));  // output: List
  3. Console.WriteLine(nameof(List<int>.Count));  // output: Count
  4. Console.WriteLine(nameof(List<int>.Add));  // output: Add
  5. var numbers = new List<int> { 1, 2, 3 };
  6. Console.WriteLine(nameof(numbers));  // output: numbers
  7. Console.WriteLine(nameof(numbers.Count));  // output: Count
  8. Console.WriteLine(nameof(numbers.Add));  // output: Add

常见的引用场景,在抛参数异常的时候

  1. if (func == null)
  2. throw new ArgumentNullException(nameof(func));
  1. class NameofExpressions
  2. {
  3. //旧方法:当参数变化的时候,被引用的地方需要同步修改
  4. public void OldMethod(int account1)
  5. {
  6. if(account1 < 100)
  7. {
  8. throw new ArgumentException("参数account1值不能小于100");
  9. }
  10. else
  11. {
  12. //其他操作
  13. }
  14. }
  15. //新方法:使用nameof当参数变化时会在引用的地方同步变化,避免硬编码
  16. //nameof里面可以是:类名,方法名,参数名,属性名
  17. public void NewMethod(int account1)
  18. {
  19. if(account1 < 100)
  20. {
  21. throw new ArgumentException($"参数{nameof(account1)}值不能小于100");
  22. }
  23. else
  24. {
  25. //其他操作
  26. }
  27. }
  28. 原文链接:https://blog.csdn.net/Tiger_shl/article/details/89981115

 

来自  https://blog.csdn.net/qianxi8888/article/details/98673711



[C#6] 2-nameof 运算符

0. 目录

C#6 新增特性目录

1. 老版本的代码

 1 using  System;
 2 namespace csharp6
 3 {
 4     internal class Program
 5     {
 6         private static void Main(string[] args)
 7         {
 8             if (args==null)
 9             {
10                 throw new ArgumentNullException("args");
11             }
12         }
13     }
14 }

这段代码并没什么问题,运行良好。随着时间的推移,有一天,我觉得args这个参数名不合适,想改一个更直观的名字filePaths,表示我要接受一个文件路径的数组。然后我们就直接把args这个名字给重构了,but,把 throw new ArgumentNullException("args"); 给忘了(resharper重构可能会同时重构这个名字),因为它仅仅是个字符串,书写的时候容易拼错,重构的时候也无法对它进行一个是否需要重构的分析,导致一些麻烦事情。

那么nameof运算符的目的就是来解决这个问题的。

2. nameof 运算符

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

 1 using  System;
 2 namespace csharp6
 3 {
 4     internal class Program
 5     {
 6         private static void Main(string[] args)
 7         {
 8             if (args==null)
 9             {
10                 throw new ArgumentNullException(nameof(args));
11             }
12         }
13     }
14 }

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

"args"方式的IL代码:

 1 .method private hidebysig static void  Main(string[] args) cil managed
 2 {
 3   .entrypoint
 4   // Code size       22 (0x16)
 5   .maxstack  2
 6   .locals init ([0] bool V_0)
 7   IL_0000:  nop
 8   IL_0001:  ldarg.0
 9   IL_0002:  ldnull
10   IL_0003:  ceq
11   IL_0005:  stloc.0
12   IL_0006:  ldloc.0
13   IL_0007:  brfalse.s  IL_0015
14   IL_0009:  nop
15   IL_000a:  ldstr      "args"
16   IL_000f:  newobj     instance void [mscorlib]System.ArgumentNullException::.ctor(string)
17   IL_0014:  throw
18   IL_0015:  ret
19 } // end of method Program::Main

nameof(args)方式的IL代码:

 1 .method private hidebysig static void  Main(string[] args) cil managed
 2 {
 3   .entrypoint
 4   // Code size       22 (0x16)
 5   .maxstack  2
 6   .locals init ([0] bool V_0)
 7   IL_0000:  nop
 8   IL_0001:  ldarg.0
 9   IL_0002:  ldnull
10   IL_0003:  ceq
11   IL_0005:  stloc.0
12   IL_0006:  ldloc.0
13   IL_0007:  brfalse.s  IL_0015
14   IL_0009:  nop
15   IL_000a:  ldstr      "args"
16   IL_000f:  newobj     instance void [mscorlib]System.ArgumentNullException::.ctor(string)
17   IL_0014:  throw
18   IL_0015:  ret
19 } // end of method Program::Main

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

3. nameof 注意事项

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

 1 using static System.Console;
 2 using CC = System.ConsoleColor;
 3 
 4 namespace csharp6
 5 {
 6     internal class Program
 7     {
 8         private static void Main()
 9         {
10             WriteLine(nameof(CC));//CC
11             WriteLine(nameof(System.ConsoleColor));//ConsoleColor
12         }
13     }
14 }

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

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

4. 参考

C#语言参考-运算符:nameof

作者:Blackheart



来自 https://www.cnblogs.com/linianhui/archive/2016/07/03/csharp6_nameof-operator.html




最重要的是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
编程是个人爱好


来自  https://www.cnblogs.com/cdaniu/p/15501498.html


普通分类: