Tuesday, May 25, 2010

A case for a nameof() operator

Refactoring your code has come a long way, especially with tools like Resharper one seldom worries about changing namespaces, renaming classes or extracting methods.
But one major breaking point still exists: Using property names as strings. And C# contains two very popular interfaces in need of property name strings.
INotifyPropertyChanged:
public string Name {
  get { return name; }
  set {
   name = value;
   InvokePropertyChanged("Name");
  }
 }

and WPFs dependency properties:
public static readonly DependencyProperty 
  ViewModelProperty = 
    DependencyProperty.Register("ViewModel",
                                typeof(MyViewModel),
                                typeof(UserView));

Both interfaces, especially with the rise of WPF/Silverlight applications, are used quite a lot. And it is not only the newbie programmer who will inadvertently break some code because he forgot to change the string when renaming a property. And while WPFs dependency properties will at least throw an exception in most cases bugs will slip in for the property changes or other interfaces which rely on the correct strings.
Since the beginning of C# people searched for solutions which do not break on refactoring, and at least since LINQ there is a viable workaround as LINQ queries have the unique property of containing string representations on their member expression parts:
public string ParsePropertyName<T>
(Expression<Func<T>> expression)
{
return ((MemberExpression)expression.Body).Member.Name;
}
...
public string Name {
  get { return name; }
  set {
   name = value;
   InvokePropertyChanged(
     ParsePropertyName(()=>this.Name);
  }
 }
While this simple solution has drawbacks (e.g. when no instance of a class is available) it seems to be used quite often as its described and discussed quite a lot. E.g. here here here here or here.

Even though the solution remains what it is: a hacky workaround.
And that is why I would propose adding a simple nameof() operator instead. It would allow us to get rid of all the fluff we add to get the name of a property and would let us write this code instead:
Code:
public string Name {
  get { return name; }
  set {
   name = value;
   InvokePropertyChanged(nameof(Name));
  }
 }

The compiled code would still look the same, without the performance drawbacks of LINQ queries, and it wouldn't break on refactoring. As an added bonus we get the functionality on methods, events... you name it.
I rest my case, what does the jury think?

Submit this story to DotNetKicks

1 comment:

Jax said...

I AGREEEEEEEEE.
In the strongest terms possible.