I was reading about the new nameof
keyword in C# 6.
I want to know how can I implement INotifyPropertyChanged
using this keyword, what are the prerequisites (of course other than C# 6) and how it will effect the performance of my MVVM application?
It would look like this:
public string Foo
{
get
{
return this.foo;
}
set
{
if (value != this.foo)
{
this.foo = value;
OnPropertyChanged(nameof(Foo));
}
}
}
The nameof(Foo)
will be substituted with the "Foo" string at compile time, so it should be very performant. This is not reflection.
CallerMemberName
, and unfortunately is not as comical as infoof
. –
Accrue CallerMemberName
is only available in .NET 4.5. Nameof
comes with the C# compiler so you'll still be able to target older .NET frameworks. –
Caster CallerMemberName
is also a compiler-powered feature so can be taken out of the .NET 4.5 dependency. I would personally change to nameof
for the other reason that the code is more explicit and less is hidden from the caller's perspective. –
Accrue nameof(Foo)
is enough since the property is certainly in scope. If you want to qualify for some reason, isn't nameof(this.Foo)
better than nameof(MyClass.Foo)
for a non-static member? I have not tried to actually compile any of this. –
Leadsman [CallerMemberName]
has the advantage simply because nameof
doesn't solve the pedanticity (?) problem, i.e. you still have to write the enclosing property's name manually in each property. At that point you might as well just type a magic string there. Whereas [CallerMemberName]
is less human-error-prone because you write the same line of code in each and the compiler takes care of getting the correct property name. –
Toneytong It's just a matter of using nameof()
instead of the magic string. The example below is from my blog article on the subject:
private string currentTime;
public string CurrentTime
{
get
{
return this.currentTime;
}
set
{
this.currentTime = value;
this.OnPropertyChanged(nameof(CurrentTime));
}
}
Since it is evaluated at compile-time, it is more performant than any of the current alternatives (which are also mentioned in the blog article).
Here's a complete code sample of a class using the new C# 6.0 sugar:
public class ServerViewModel : INotifyPropertyChanged {
private string _server;
public string Server {
get { return _server; }
set {
_server = value;
OnPropertyChanged(nameof(Server));
}
}
private int _port;
public int Port {
get { return _port; }
set {
_port = value;
OnPropertyChanged(nameof(Port));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
With this, you get the nameof()
operator, the null-conditional operator ?.
, and an expression-bodied function (the OnPropertyChanged
definition).
I've found it's a lot easier to use PropertyChanged.Fody as you end up with less mistakes and a hell of a lot cleaner code, see - https://github.com/Fody/PropertyChanged
All you have to do is label up your class with ImplementPropertyChanged
attribute:
[ImplementPropertyChanged]
public class Person
{
public string GivenNames { get; set; }
public string FamilyName { get; set; }
public string FullName
{
get
{
return string.Format("{0} {1}", GivenNames, FamilyName);
}
}
}
And after build it gets transformed in to:
public class Person : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string givenNames;
public string GivenNames
{
get { return givenNames; }
set
{
if (value != givenNames)
{
givenNames = value;
OnPropertyChanged("GivenNames");
OnPropertyChanged("FullName");
}
}
}
string familyName;
public string FamilyName
{
get { return familyName; }
set
{
if (value != familyName)
{
familyName = value;
OnPropertyChanged("FamilyName");
OnPropertyChanged("FullName");
}
}
}
public string FullName
{
get
{
return string.Format("{0} {1}", GivenNames, FamilyName);
}
}
public virtual void OnPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
See the documentation for INotifyPropertyChanged.PropertyChanged Event
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
© 2022 - 2024 — McMap. All rights reserved.
nameof
should formalise that. – AccrueOnPropertyChanged("(?<propName>\w+)"\);
toOnPropertyChanged(nameof(${propName}));
– Ruthven