65.9K
CodeProject is changing. Read more.
Home

WPF: Getting Rid of "magic strings" Reduces Speed

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.11/5 (3 votes)

May 3, 2016

CPOL

1 min read

viewsIcon

15466

downloadIcon

69

Speed reduction that may occur when using expressions instead of string constants in INotifyChanged paradigm and a way to work around this

Introduction

A common practice is to use lambda expressions instead of string constants - "magic strings" - as the names of the properties in the INotifyChanged paradigm: something like NotifyPropertyChanged(()=>Property); instead of NotifyPropertyChanged("Property");
We will show that this reduces the speed of Binding execution. Also, we will show a trivial way to work around this.

Property Name Infer From Expression

Generally such construction requires a property name infer from the expression:

public static string NameInfer<T>( Expression<Func<T>> itemExpression )
{
    switch ( itemExpression.Body.NodeType )
    {
        case ExpressionType.Constant:
        default:
            return ( ( itemExpression.Body as ConstantExpression ).Value as String );

        case ExpressionType.MemberAccess:
            return ( ( itemExpression.Body as MemberExpression ).Member.Name );
    }
}

This calculation takes a certain time. Below - the results of time testing. An average of twenty thousand fold sendings of a text ("Lorem ipsum...") to property is calculated. Left side column - result for string constant property name; middle column - result for expression derived property name:

Numerical values above may seem ridiculous, but with intensive communication between View and ViewModel can be significant; timing difference also becomes important in the case of ViewModel - ViewModel communications.

Repair

Fortunately repair is straightforward and somewhat dull. It is enough to declare readonly string variables and evaluate them once in a ViewModel's constructor using expression to string conversion, and to use these variables instead of constant property names in all further calls to NotifyPropertyChanged - something like in the code snippet below:

    ...
private readonly string sr_view1Text2;
    ...
#region ctor
public View1Model()
{
    ...
    sr_view1Text2 = NameTypeHelper.NameInfer( ( ) => View1Text2 );
    ...
}
#endregion ctor

    ...
private string _view1Text2;
public string View1Text2
{
    get { return _view1Text2; }
    set
    {
        if ( _view1Text2 != value )
        {
            _view1Text2 = value;
            NotifyPropertyChanged( sr_view1Text2 );
        }
    }
}

Below - the results of testing: left side column - timing for constant string property name, middle column - for expression derived property name and the right side column - for readonly string variable which value is derived from expression only once.

Timings for "magic strings" property names and readonly string variable property names are the same.

History

  • 3rd May, 2016: Initial version