MVVM Part 3: ViewModelBase

Note: This posting is part of a series. See MVVM-Library for other parts and download.

Class Diagram of ViewModelBase It’s time for our first real “ViewModel” class: ViewModelBase.

As a ViewModel is – I already said before – databound to the UI it inherits NotifyKnownPropertyChanged to provide base support for Data Binding.

Data Binding to a WPF UI brings up another problem: The PropertyChanged event may only be raised in the UI thread.

In order to handle forbidden accesses from other threads and to make “Invoke”-scenarios possible, ViewModelBase remembers the dispatcher of the thread which created it. The methods for this purpose should be self-explanatory.

Note: ViewModel hides NotifyKnownPropertyChanged.OnPropertyChanged in order to perform a (debug-only) check ensuring it was called from the right thread. I thought a while if it would be better to make NotifyKnownPropertyChanged.OnPropertyChanged virtual and implement an auto-invoke solution.  As ViewModel classes are not thread safe (in general), however, but may be able to deal with callbacks (etc.) executing in other threads, this approach is ok in my opinion. Derived classes must not call OnPropertyChanged from another thread – if they do though there will only be an error when using the debug build.

Today, I won’t post an sample project because ViewModelBase makes only sense if it is inherited. You can download the updated ViewModel project (without the sample for the last part) here: MVVM-Library.

Posted in My interpretation of MVVM, WPF. Tags: , , , , , . Comments Off on MVVM Part 3: ViewModelBase

Pitfalls and Best Practices to prevent them #2: Operator priority

Example

class Program
{
    static void Main(string[] args)
    {
        Foo foo = new Foo();
        foo.Test = "Baz";

        foo.Bar(null);
    }
}

public sealed class Foo
{
    public string Test
    {
        get;
        set;
    }

    public void Bar(Foo other)
    {
        this.Test += "Value:" + other == null ? "<null>" : other.Test;
    }
}

What does it do?

The method Bar contains an expression using the tertiary operator to handle the case that other is null.

In this case “<null>” is appended instead of the value of other.Test.

However, this is only what the code should do. In fact, there occurs a NullReferenceException.

Doku says

C# Language Specification (7.2.1: Operator precedence and associativity):

The following table summarizes all operators in order of precedence from highest to lowest:

Section Category Operators
7.5 Primary x.y f(x) a[x] x++ x– new typeof default checked unchecked delegate
7.6 Unary + – ! ~ ++x –x (T)x
7.7 Multiplicative * / %
7.7 Additive + –
7.8 Shift << >>
7.9 Relational and type testing < > <= >= is as
7.9 Equality == !=
7.10 Logical AND &
7.10 Logical XOR ^
7.10 Logical OR |
7.11 Conditional AND &&
7.11 Conditional OR ||
7.12 Null coalescing ??
7.13 Conditional ?:
7.16, 7.14 Assignment and lambda expression = *= /= %= += -= <<= >>= &= ^= |= =>

 

Problem

I already mentioned: There occurs a NullReferenceException.

Let’s take a closer look to the problematic line:

this.Test += "Value:" + other == null ? "<null>" : other.Test;

As the += operator has a lower precedence than the others, we can say: The following part is executed before the assignment:

"Value:" + other == null ? "<null>" : other.Test;

What about this part now? Well, as the +-operator has a higher precedence than the ?:-operator, we are now able to write what the compiler actually does in another way:

string temp = "Value:" + other; //Will always be "Value:ConsoleApplication1.Foo"
temp = temp == null ? "<null>" : other.Test; //As temp is never null, temp will be other.Test
this.Test += temp;

You should see the problem in the second line now: other.Test is accessed irrespective of its “nullstate”.

How to solve?

As always (:-)) there is a simple solution: Make clear what you want by using brackets:

this.Test += "Value:" + (other == null ? "<null>" : other.Test);

The code not only gets “right” now, it’s also easier to understand.

Generalization / Best Practice:

In (complex) statements, do not hesitate to use brackets; better “safe than sorry”. They make the code clearer and prevent errors originating in misjudged operator precedence. Two very important cases are the ?:-operator and all logical operators.

DotNetKicks Image
Posted in Pitfalls. Tags: , , . Comments Off on Pitfalls and Best Practices to prevent them #2: Operator priority