Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any benefit of using the nameof operator instead of the CallerMemberNameAttribute to notify property changes in .NET 4.5.3?

With the advent of .NET 4.5.3, WPF developers now have three (or more) ways to notify the INotifyPropertyChanged Interface of property changes. Basically, my question is Which of the two methods introduced from.NET 4.5 onwards is the more efficient way to notify property changes and whether either way has any benefit when being used in WPF?

Background

For those not so familiar with this subject, here are the main three methods. The first is the original, more error prone method of simply passing a string:

public string TestValue
{
    get { return testValue; }
    set { testValue = value; NotifyPropertyChanged("TestValue"); }
}

protected virtual void NotifyPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

The second method was introduced in .NET 4.5; the CallerMemberNameAttribute:

public string TestValue
{
    get { return testValue; }
    set { testValue = value; NotifyPropertyChanged(); }
}

protected virtual void NotifyPropertyChanged([CallerMemberName]string propertyName = "")
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

The third and most recent method was (or will soon be) introduced in C#6.0 as part of .NET 4.5.3; the nameof Operator:

public string TestValue
{
    get { return testValue; }
    set { testValue = value; NotifyPropertyChanged(nameof(TestValue)); }
}

protected virtual void NotifyPropertyChanged(string propertyName)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

My own assumption would be that the original, more error prone method of simply passing a string would be the most efficient, as I can only imagine that the other two methods use some form of reflection. However, I'm really keen to find out which of the other two methods is more efficient and whether there would actually be any difference between using the CallerMemberNameAttribute attribute and the nameof operator in a WPF context.

like image 814
Sheridan Avatar asked Feb 08 '15 17:02

Sheridan


People also ask

What is Nameof used for?

C# NameOf operator is used to get name of a variable, class or method. It returns a simple string as a result. In error prone code, it is useful to capture a method name, in which error occurred. We can use it for logging, validating parameters, checking events etc.

Does Nameof use reflection?

Does it use Reflection? nameof is apparently as efficient as declaring a string variable. No reflection or whatsoever!

How does Nameof work C#?

The nameof operator accepts the name of code elements and returns a string literal of the same element. The parameters that the nameof operator can take can be a class name and all its members like methods, variables and constants and returns the string literal.

When was Nameof added to C#?

The nameof operator, added in C# 6.0, addresses this — it allows capturing the string names of symbols that are in the scope.


2 Answers

About efficiency: using a string directly, CallerMemberNameAttribute, nameof are all exactly the same since the string is injected by the compiler at compile-time. There's no reflection involved.

We can see that using TryRoslyn that produces this for CallerMemberNameAttribute:

public string TestValue
{
    get { return this.testValue; }
    set { this.testValue = value; this.NotifyPropertyChanged("TestValue"); }
}
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
    if (this.PropertyChanged != null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

And this for nameof:

public string TestValue
{
    get { return this.testValue; }
    set { this.testValue = value; this.NotifyPropertyChanged("TestValue"); }
}
protected virtual void NotifyPropertyChanged(string propertyName)
{
    if (this.PropertyChanged != null)
    {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Since at runtime all options are simply a string there's no problem with the WPF context.

About convenience: CallerMemberNameAttribute requires you to have an optional parameter while nameof doesn't but nameof requires you to specify the property while CallerMemberNameAttribute doesn't.

I predict that nameof would turn out to be so popular that it would be much simpler to use it instead.

like image 84
i3arnon Avatar answered Nov 15 '22 02:11

i3arnon


The CallerMemberNameAttribute can only be used on the called function the get the name of the caller function.

The nameof operator goes way beyond that. It can be used anywhere.

If you want to reason about it just in the scope of WPF data binding, take this example:

public string FullName
{
   get
   {
       return string.Format(
           "{0} {1}",
           this.firstName,
           this.lastName);
   }
}

public string FirstName
{
   get
   {
       return this.firstName;
   }
   set
   {
       if (value != this.firstName)
       {
           this.firstName = value;
           NotifyPropertyChanged(nameof(FirstName));
           NotifyPropertyChanged(nameof(FullName));
        }
   }
}

public string LasttName
{
   get
   {
       return this.lastName;
   }
   set
   {
       if (value != this.lastName)
       {
           this.lastName = value;
           NotifyPropertyChanged(nameof(LasttName));
           NotifyPropertyChanged(nameof(FullName));
        }
   }
}
like image 28
Paulo Morgado Avatar answered Nov 15 '22 03:11

Paulo Morgado