„Prism spinnt!“ oder “static const vs. static readonly”

Es gibt diese Bugs über die Entwickler stundenlang philosophieren können und bei deren Erläuterung man reihenweise das Klatschen flacher Hände auf gerunzelten Stirnen vernimmt, weil man es ja eigentlich hätte wissen können. Nachfolgende Schilderungen gehören eindeutig in diese Kategorie…

Dank Dotnetpro und Co. sollte das Framework Prism mittlerweile recht bekannt sein. Es dient dazu WPF oder Silverlight Applikationen zur Laufzeit dynamisch „zusammen zu stöpseln“. Statt also während der Entwicklung fest zu legen welches UserControl wo hin geladen wird, legt man nur Regionen für die Steuerelemente fest und deren Inhalt wird dann dynamisch beim Start an genau diesen Stellen platziert. Dadurch können sie ohne weiteres ausgetauscht, wieder verwendet oder neu angeordnet werden.

Soll Zustand der Prism Anwendung
Soll Zustand der Prism Anwendung mit einem TabControl in dem dynamisch die Views angeordnet werden.

Diese Regionen werden dabei  von einem so genannten RegionManager verwaltet bei dem sie und ihre zugehörigen Views registriert werden. Prism übernimmt dann die Auflösung aller Abhängigkeiten und die  Instanziierung der notwendigen Klassen.

Damit die Views sich aber bei den Regionen registrieren können, müssen jene identifiziert werden und das tut man in aller Regel über Strings. Und weil es natürlich sehr fehleranfällig ist, diese String immer und immer wieder einzugeben gilt es als Best-Practice eine statische Klasse zu schaffen in der all jene gesammelt werden. Somit werden im Xaml oder C# Code dann nur noch Variablen verwendet und die eigentlichen Strings sind völlig egal.

<TabControl p:RegionManager.RegionName="{x:Static c:Constants.MainRegion}"/>

Eigentlich, denn was passiert, wenn man die Strings ändert? Hier kommt es sehr stark darauf an wie man sie in der statischen Klasse hinterlegt hat, denn dafür gibt es zwei bzw. drei Wege. Der übliche und von StyleCop und R# geforderte ist dabei die Verwendung von konstanten Variablen:

public static class Constants
{
   public static const string ControlRegion = "controlRegion";
   public static const string MainRegion = "mainContentRegion";
   public static const string MenuRegion = "menuRegion";
}

Dies hat einen gewissen Vorteil, denn konstante Variablen werden zur Kompilier-Zeit aufgelöst und ihr tatsächlicher Wert wird dann vom Compiler an all jene Stellen geschrieben an denen sie referenziert werden; was auch der Grund ist warum nur die üblichen Wertetypen und Strings als const gekennzeichnet werden können. Auf diese Weise spart man zur Laufzeit das Fitzelchen Rechenzeit was bei einer üblichen statischen Variable verloren geht, weil erst deren Referenz aufgelöst und ihr Wert ausgelesen werden muss.

Ist Zustand mit falscher Namenszuordnung.
Fehlerhafter Ist-Zustand weil die Region aufgrund des falschen Namens nicht zugeordnet werden kann.

Der zweite und dritte Weg besteht dem gegenüber darin, eine statische nur lesbare Variable bzw. statische Property zu verwenden. Hier wird der Wert mit jedem Zugriff erneut ausgelesen, was nicht ganz so performant ist aber den Vorteil hat, dass die Werte nicht in die Aufrufer hinein kompiliert werden.

Ich gebe zu, so wirklich neu ist das für die Meisten sicher nicht. Es wird im Alltag aber schnell vergessen, wodurch dann Situationen entstehen bei denen man sich die Haare rauft.  Denn wenn man zum Beispiel im Zusammenhang mit Prism nicht darauf achtet und einfach mal die Strings der Konstanten ändert ohne alle abhängigen Dlls neu zu kompilieren, wundert man sich recht schnell warum die Views nicht mehr angezeigt werden und das obwohl man doch eigentlich „nichts“ geändert hat.

In dem Fall dann also einfach noch einmal alles komplett kompilieren, die strings nicht const mache oder halt niemals ändern…