© DrHitch/Shutterstock.com
Einblicke in C# 6.0

3 C# 6.0 in MVVM-Apps


Die sechste Version von C# bietet zahlreiche Neuerungen wie den Null-conditional Operator, die nameof-Expression, die mächtige String-Interpolation und natürlich Expression-bodied Members. Mit all diesen Neuerungen lässt sich auch der Code einer klassischen Model-View-ViewModel-basierten (MVVM) Windows-Applikation deutlich leserlicher und kompakter gestalten. Dieses Kapitel zeigt einige der typischen Fälle in einer MVVM-Applikation, in denen C# 6.0 den Entwicklern das Leben leichter macht.

Wer kennt sie nicht, die zahlreichen Codestellen in MVVM-Apps, die für den Liebhaber sauberen Codes noch nicht ganz sauber genug sind: Für das Auslösen eines PropertyChanged-Events muss an diversen Stellen immer noch ein String angegeben werden, obwohl eigentlich der Property-Name gewünscht ist. Wird die Property umbenannt, darf man nicht vergessen, auch den String umzubenennen. Wird dies dann doch einmal versäumt, funktioniert das Aktualisieren des User Interface nicht mehr, da die Data Bindings nur auf das Event lauschen, das genau den gebundenen Property-Namen in den Event-Argumenten enthält.

Genau für dieses Problem entstanden in der Vergangenheit zahlreiche Workarounds, wie beispielsweise das Verwenden von Property Expressions. Dabei wird eine Lambda Expression angegeben, um darüber den Property-Namen auflösen zu können. Diese Lambda Expressions haben gegenüber dem klassischen String den Vorteil, dass sie zu einem Kompilierfehler führen, wenn die Property umbenannt und dabei vergessen wird, die Lambda Expression entsprechend anzupassen. Folglich wird das Event immer mit dem richtigen Property-Namen ausgelöst. Klingt eigentlich perfekt. Wäre da nicht der kleine Punkt, dass die Lambda Expressions bei umfangreichen Event-Auslösungen für Performanceeinbußen sorgen. Wenn es also um Performance geht – in welcher WPF- oder Windows-10-App geht es das nicht – greifen Entwickler dann doch wieder zum String. In .NET 4.5 kam im Zusammenhang mit C# 5.0 das CallerMemberName-Attribut hinzu, das etwas Abhilfe schafft, aber auch nicht für alle Fälle ausreicht. Mit C# 6.0 kommt endlich eine Lösung: Mit dem neuen nameof-Keyword lässt sich ganz einfach der Name einer Property abgreifen. Fantastisch!

Jetzt, wo das Thema PropertyChanged-Event schon angeschnitten ist, ist es eine gute Idee, mit einer Aufräumaktion an der Wurzel zu starten: dort, wo das PropertyChanged-Event ausgelöst wird. Wie heißt es so schön: Der Fisch fängt am Kopf an zu stinken. Bezogen auf .NET-Code bedeutet dies, dass es in der Basisklasse losgeht.

Das Auslösen des „PropertyChanged“-Events

Das PropertyChanged-Event wird oftmals mit einer Hilfsmethode namens OnPropertyChanged ausgelöst. Diese Hilfsmethode wird üblicherweise in einer ViewModelBase-Klasse implementiert, wie sie in Listing 3.1 zu sehen ist. Hier fällt auf, dass das PropertyChanged-Event zuerst in einer lokalen Variablen namens handler gespeichert wird. Dann wird mit einem if-Statement geprüft, ob diese handler-Variable nicht null ist, bevor die handler-Variable genutzt wird, um das eigentliche PropertyChanged-Event auszulösen.

public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if(handler!=null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}

Listing 3.1

Das Zwischenspeichern in eine lokale handler-Variable wirkt auf den ersten Blick überflüssig. Doch es ist von großer Bedeutung, wenn mehrere Threads ins Spiel kommen. Durch das Zwischenspeichern in der lokalen handler-Variablen wird eine Referenz auf das Event bzw. auf die Delegates gehalten. Dadurch wird folgender Fehlerfall ausgeschlossen: Das Event ist bei der Bedingung des if-Statements nicht null, der Code kommt somit in den Body des if-Statements. Bevor aber das eigentliche Auslösen des Events stattfindet, wurde durch einen anderen Thread der letzte Delegate entfernt, und somit ist das Event plötzlich innerhalb des if-Statements null. Folglich fliegt dem Entwickler oder – noch schlimmer – dem Benutzer eine NullReferenceException um die Ohren. Mit dem etwas umständlichen Zwischenspeichern in die lokale handler-Variable wird genau dieser Fehlerfall vermieden. Doch in Zeiten von C# 6.0 wird das Ganze noch einen Tick einfacher.

Der Null-conditional Operator

Mit dem Null-conditional Operator lässt sich das PropertyChanged-Event auf „not null“ prüfen, indem einfach, wie in Listing 3.2 dargestellt, ein Fragezeichen an das PropertyChanged-Event angehängt wird. Die Invoke-Methode auf dem Event wird somit nur dann aufgerufen, wenn das Event nicht null ist. Und zur Freude aller Event-auslösenden Entwickler: Das Ganze ist threadsicher. Das lästige Zwischenspeichern in eine lokale handler-Variable ist somit Schnee von gestern.

protected virtual void OnPropertyChanged(string propertyName)
{
PropertyCh...

Neugierig geworden?

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang