C# v6 Features–Nameof Operator
One of the cool new features coming in C# v6 is the nameof operator. This handy little operator solves a common code smell, string literals for programmatic items. Let’s take a simple example.
static void Foo ( string value ) { if (value == null) throw new ArgumentNullException("value"); }
What is wrong with this code? Give you a hint, rename the parameter to something else. Using parameter names in exception constructors, as part of logging messages and many other places is simply a bad smell. Renaming the parameter requires that you find all the places it is used as a string literal as well. If you forget to rename one then it will still compile but it is just wrong. One of the common code analysis rules that people use is to detect bad parameter names in exception constructors but there are other cases it simply cannot detect.
Parameter Names
With the nameof
operator this problem goes away.
static void Foo ( string value ) { if (value == null) throw new ArgumentNullException(nameof(value)); }
Renaming the parameter (using the Rename option) will also rename the operator references. The return type of this expression is string
. The value returned is the stringified version of the argument (the source name). It accepts an expression but the expression is limited. At this time the following are allowed.
- Simple names such as variable and member names
- Member access (i.e. String.Join)
- Base and this members (i.e. this.SomeString)
There are still some cases that are unclear or being changed but in general it will return the equivalent value of you putting the given expression in a string literal. Note that overloaded methods don’t really matter here as a method name is a method name irrelevant of the actual method selected. Generic and parameter types are not included.
One caveat to the expressions is that aliases are not allowed (i.e. string, dynamic, etc.) but the regular type names are (i.e. String, Int64).
//Valid var str2 = nameof(String); //Not valid var str3 = nameof(string);
Let’s look at some more use cases.
INotifyPropertyChanged
The INotifyPropertyChanged interface is heavily used in UI frameworks to detect when properties on displayed objects change. Here is a typical implementation.
class Employee : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public string Name { get { return m_name ?? ""; } set { if (m_name != value) { m_name = value; OnPropertyChanged("FirstName"); }; } } protected virtual void OnPropertyChanged ( string name ) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name)); } private string m_name; }
There have been attempts to resolve the magic string craziness via base classes or helper methods but they just muddy things up. Did you notice that the magic string didn’t match the property name? Here’s the new version using nameof
.
class Employee : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public string Name { get { return m_name ?? ""; } set { if (m_name != value) { m_name = value; OnPropertyChanged(nameof(Name)); }; } } protected virtual void OnPropertyChanged ( string name ) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name)); } private string m_name; }
MVC Views
Yet another common place for magic strings is in MVC action links. For MVC links you need the controller name and action (view) name.
@Html.ActionLink("Home", "Index", "Home")
Here’s the updated version using nameof
.
@Html.ActionLink("Home", nameof(HomeController.Index), typeof(HomeController))
(NOTE: This currently generates an error in the 2015 Preview)
There are any number of other cases where the nameof
operator will come in handy. The biggest issue is going to be knowing the rules for what expressions work and what don’t.