C# 6 Preview: nameof expressions

One of the new features in C# 6 is the new nameof operator. This will give you the name of a variable or type name, for instance nameof(id) gives you “id”. It’s a very simple feature. Let’s see a couple of examples where it is useful.

The simplest example is when checking whether arguments are null. I’ve got this simpleĀ Person class:

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public Person(string firstName, string lastName)
        {
            if (firstName == null)
                throw new ArgumentNullException("firstName");
            if (lastName == null)
                throw new ArgumentNullException("lastName");

            this.FirstName = firstName;
            this.LastName = lastName;
        }
    }

Notice how I’m passing magic strings into the ArgumentNullExceptions. If I rename the arguments, then I must remember to update the magic strings as well.

Let us now take advantage of the new nameof() operator:

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public Person(string firstName, string lastName)
        {
            if (firstName == null)
                throw new ArgumentNullException(nameof(firstName));
            if (lastName == null)
                throw new ArgumentNullException(nameof(lastName));

            this.FirstName = firstName;
            this.LastName = lastName;
        }
    }

It’s evident that with this change, if you rename the arguments, you will have to rename them throughout, or you will get a compiler error. No more magic strings.

Another scenario where this is really useful is when you are dealing with NotifyPropertyChanged in a WPF application. After implementing INotifyPropertyChanged in my ViewModel, I added the following property with a backing field to facilitate data binding:

        private string currentTime;

        public string CurrentTime
        {
            get
            {
                return this.currentTime;
            }
            set
            {
                this.currentTime = value;
                this.OnPropertyChanged("CurrentTime");
            }
        }

Here we have the same problem as before: we are using magic strings, and that can be problematic especially if we refactor our property and forget to update the property name in the string. Over the years, MVVM library developers have come up with various ways to mitigate this unpleasant scenario, including passing backing fields as ref parameters when raising the PropertyChanged event, using CallerMemberName, or using expression trees to pass in the property itself. nameof() again makes things a lot easier, as shown below. Even better, it is evaluated at compile-time, so there is no performance penalty associated with its use.

        private string currentTime;

        public string CurrentTime
        {
            get
            {
                return this.currentTime;
            }
            set
            {
                this.currentTime = value;
                this.OnPropertyChanged(nameof(CurrentTime));
            }
        }

4 thoughts on “C# 6 Preview: nameof expressions”

  1. This is a very useful feature, but PLEASE tell me this will work for method names, not just properties & variables. So I can write e.g.:

    Menu.AddAction(nameof(DoSomething));

    Also, I assume that nameof will work for a property/variable/(method) specified on another object, not just ‘this’ e.g.:

    nameof(x.Foo)

    is that correct?

    1. I have just checked for you, and both scenarios you mentioned are supported.

      nameof(DoSomething), where DoSomething is a method, gives you “DoSomething”.

      nameof(Person.PersonDoNothing), where PersonDoNothing is a non-static method in class Person, returns “PersonDoNothing”, i.e. just the method name, not the fully-qualified name.

Leave a Reply to Richard Pawson Cancel reply

Your email address will not be published. Required fields are marked *