7

Form Build your own MVVM I have the following code that lets us have typesafe NotifyOfPropertyChange calls:

public void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property)
{
    var lambda = (LambdaExpression)property;
    MemberExpression memberExpression;
    if (lambda.Body is UnaryExpression)
    {
        var unaryExpression = (UnaryExpression)lambda.Body;
        memberExpression = (MemberExpression)unaryExpression.Operand;
    }
    else memberExpression = (MemberExpression)lambda.Body;
    NotifyOfPropertyChange(memberExpression.Member.Name);
 }

How does this approach compare to standard simple strings approach performancewise? Sometimes I have properties that change at a very high frequency. Am I safe to use this typesafe aproach? After some first tests it does seem to make a small difference. How much CPU an memory load does this approach potentially induce?

bitbonk
  • 48,890
  • 37
  • 186
  • 278
  • You might be interested in this discussion: [**Best Practices: How to implement INotifyPropertyChanged right?**](http://compositeextensions.codeplex.com/Thread/View.aspx?ThreadId=53731) – jbe Apr 30 '10 at 16:54

6 Answers6

5

What does the code that raises this look like? I'm guessing it is something like:

NotifyOfPropertyChange(() => SomeVal);

which is implicitly:

NotifyOfPropertyChange(() => this.SomeVal);

which does a capture of this, and pretty-much means that the expression tree must be constructed (with Expression.Constant) from scratch each time. And then you parse it each time. So the overhead is definitely non-trivial.

Is is too much though? That is a question only you can answer, with profiling and knowledge of your app. It is seen as OK for a lot of MVC usage, but that isn't (generally) calling it in a long-running tight loop. You need to profile against a desired performance target, basically.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
2

Emiel Jongerius has a good performance comparrison of the various INotifyPropertyChanged implementations.

http://www.pochet.net/blog/2010/06/25/inotifypropertychanged-implementations-an-overview/

The bottom line is if you are using INotifyPropertyChanged for databinding on a UI then the performance differences of the different versions is insignificant.

Simon
  • 33,714
  • 21
  • 133
  • 202
1

How about using the defacto standard

if (propName == value) return;
propName = value;
OnPropertyChanged("PropName");

and then create a custom tool that checks and refactors the code file according to this standard. This tool could be a pre-build task, also on the build server. Simple, reliable, performs.

Gerard
  • 13,023
  • 14
  • 72
  • 125
0

I use the following method in a base class implementing INotifyPropertyChanged and it is so easy and convenient:

public void NotifyPropertyChanged()
    {
        StackTrace stackTrace = new StackTrace();

        MethodBase method = stackTrace.GetFrame(1).GetMethod();

        if (!(method.Name.StartsWith("get_") || method.Name.StartsWith("set_")))
        {
            throw new InvalidOperationException("The NotifyPropertyChanged() method can only be used from inside a property");
        }

        string propertyName = method.Name.Substring(4);

        RaisePropertyChanged(propertyName);
    }

I hope you find it useful also. :-)

Joben Blom
  • 31
  • 2
  • 1
    PLease do not spam the same answer across multiple questions. If the question is a duplicate, leave a comment indicating such (or flag if you have enough reputation). If it's not a duplicate, please tailor your answer to the question asked. – George Stocker Aug 30 '12 at 00:35
0

Typesafe and no performance loss: NotifyPropertyWeaver extension. It adds in all the notification automatically before compiling...

Marc
  • 12,706
  • 7
  • 61
  • 97
0

Stack walk is slow and lambda expression is even slower. We have solution similar to well known lambda expression but almost as fast as string literal. See http://zamboch.blogspot.com/2011/03/raising-property-changed-fast-and-safe.html

Pavel Savara
  • 3,427
  • 1
  • 30
  • 35