Original link: https://code-examples.net/zh-CN/q/1e3a41c
Most importantly, nameof does not affect performance!
In the past, we used this:
// 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) { ... }
Reason - compile time security. No one can silently rename properties and break code logic. Now we can use nameof ().
What if you want to reuse the property name, such as when throwing an exception based on the property name or handling the PropertyChanged event? In many cases, you want to use attribute names.
for instance:
switch (e.PropertyName) { case nameof(SomeProperty): { break; } // opposed to case "SomeOtherProperty": { break; } }
In the first case, renaming SomeProperty will also change the name of the property, otherwise compilation will be interrupted. The last case is not.
This is a very useful way to keep code compiled and eliminate errors (sorting).
( A very good article by Eric Lippert, Why infoof didn't do it, but nameof did)
It is really useful for ArgumentException and its derived classes:
public string DoSomething(string input) { if(input == null) { throw new ArgumentNullException(nameof(input)); } ...
Now, if someone refactor the name of the input parameter, the exception will also remain up-to-date.
It is also useful where reflection must previously be used to obtain property or parameter names.
In your example, nameof(T) gets the name of the type parameter - which may also be useful:
throw new ArgumentException(nameof(T), $"Type {typeof(T)} does not support this method.");
Another use of nameof is for enumeration - usually, if you want to use the string name of the enumeration of. ToString():
enum MyEnum { ... FooBar = 7 ... } Console.WriteLine(MyEnum.FooBar.ToString()); > "FooBar"
This is actually relatively slow because. Net keeps enumeration values (that is, 7) and looks up names at run time.
Instead, use nameof:
Console.WriteLine(nameof(MyEnum.FooBar)) > "FooBar"
Now,. Net replaces the enumeration name with a string at compile time.
Another use is for INotifyPropertyChanged and logging - in both cases, you want to pass the name of the member to be called to another method:
// Property with notify of change public int Foo { get { return this.foo; } set { this.foo = value; PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.Foo)); } }
or
// Write a log, audit or trace for the method called void DoSomething(... params ...) { Log(nameof(DoSomething), "Message...."); }
The most common use case I can think of is when using the INotifyPropertyChanged interface. (basically, everything related to WPF and binding uses this interface)
Take a look at this example:
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))); } } }
As you can see, we must pass a string to indicate which property has changed. Using nameof, we can directly use the name of the attribute. It doesn't seem like a big deal. But imagine what happens when someone changes the name of the property Foo. When you use strings, the binding stops working, but the compiler does not warn you. When using nameof, a compiler error occurs that there is no attribute / parameter named Foo.
Note that some frameworks use some reflection magic to get the name of the attribute, but now that we have nameof, it is no longer necessary.
The most common usage is in input validation, such as
//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)); }
In the first case, if you refactor the method that changes the par parameter name, you may forget to make the change in ArgumentNullException. With nameof, you don't have to worry.
See also: nameof (C and Visual Basic reference)
Considering that you use variables in your code and need to get the name of the variable and print it out, you must use
int myVar = 10; print("myVar" + " value is " + myVar.toString());
Then, if someone refactor the code and use another name for "myVar", he / she will have to pay attention to the string value in the code and process it accordingly.
Instead, if you have
print(nameof(myVar) + " value is " + myVar.toString());
This will help with automatic refactoring!
One use of the nameof keyword is to programmatically set Binding in wpf.
To set the Binding, you must set the Path using the string and the nameof keyword. You can use the Refactor option.
For example, if you have IsEnable dependency property in UserControl and want to bind it to some CheckBox IsEnable in UserControl, you can use the following two codes:
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);
Obviously, the first code cannot be refactored, while the second code can be refactored.
The purpose of the nameof operator is to provide the source name of the artifact.
Generally, the source name is the same as the metadata Name:
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)); } }
But this is not always the case:
using i = System.Int32; ... Console.WriteLine(nameof(i)); // prints "i"
or
public static string Extension<T>(this T t) { return nameof(T); returns "T" }
One purpose I have always given it is to name resources:
[Display( ResourceType = typeof(Resources), Name = nameof(Resources.Title_Name), ShortName = nameof(Resources.Title_ShortName), Description = nameof(Resources.Title_Description), Prompt = nameof(Resources.Title_Prompt))]
The fact is, in this case, I don't even need the generated properties to access the resource, but now I have compile time to check whether the resource exists.
Another use case where the nameof function of C 6.0 becomes very convenient - consider things like Dapper Such a library makes DB retrieval easier. Although this is a great library, you need to hard code the attribute / field names in the query. This means that if you decide to rename a property / field, you are likely to forget to update the query to use the new field name. Using string interpolation and nameof functionality, the code becomes easier to maintain and type safe.
Examples given from links
No name
var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });
And nameof
var dog = connection.Query<Dog>($"select {nameof(Dog.Age)} = @Age, {nameof(Dog.Id)} = @Id", new { Age = (int?)null, Id = guid });