Im vergangenen Jahr standen bei Microsoft alle Zeichen auf Windows 8. Dabei drehte sich aber beileibe nicht alles nur um ein neues Betriebssystem. Auch die Einführung neuer Features bei Entwicklerwerkzeugen und Infrastruktur wurden sehr häufig direkt oder indirekt von den Anforderungen des neuen Systems getrieben. Andere, nicht mit Windows 8 zusammenhängende Bereiche – so zumindest der Eindruck bei vielen – wurden eher auf Sparflamme geköchelt. Dieser Trend lässt sich auch an der nächsten Version des .NET Frameworks ablesen. Denn vieles von dem, was uns an Neuerungen in .NET 4.5 bevorsteht, hängt irgendwie mit Windows 8 zusammen. Andererseits muss man natürlich auch sagen, dass .NET inzwischen einen derart hohen Reifegrad erreicht hat, dass evolutionäre Verbesserungen und Erweiterungen der bestehenden Features nur logisch sind und es gar keinen Anlass für dramatische Umwälzungen gab. Mit unserer Blog-Serie “Neu in .NET 4.5” möchten wir auf diese großen und kleinen Neuerungen eingehen, und natürlich insbesondere auch vorstellen, in welchem Umfang auch solche Entwickler und Projekte betroffen sind und profitieren können, die nicht direkt mit den neuen “Modern UI”-Anwendungen zu tun haben werden.
Chancen und Risiken
Bereits heute sind viele unserer Kunden sehr daran interessiert, sich über die Neuerungen in .NET 4.5 zu informieren, und wie ihre Teams direkt von Verbesserungen und neuen Funktionen profitieren können. Einzelne Stichworte und Themen, die man bereits über Blogs, Artikel oder direkt von Microsoft erfahren hat, haben den Appetit geweckt und klare Potenziale eines Updates aufgezeigt. Andererseits herrscht vielerorts auch Unklarheit und Verunsicherung darüber, wer .NET 4.5 überhaupt nutzen kann, und welche Gefahren ein Team beim Aktualisieren seiner Projekte vielleicht eingeht. Unsere Serie wird in kommenden Teilen im Detail auf einige der wirklich sehr interessanten neuen Features eingehen. Die vorliegende Einführung jedoch soll .NET 4.5 zunächst in den richtigen Kontext stellen und auch auf Klippen hinweisen, die man in seinen Projekten erst einmal umschiffen muss.
Plattform-Support
Einer der wichtigsten Punkte, der für einige Entwickler bereits ein K.O.-Kriterium sein könnte, ist die kurze Liste unterstützter Client-Betriebssysteme von .NET 4.5:
- Windows Vista SP2
- Windows 7
- Windows 8 (im Lieferumfang)
Unterstützt werden jeweils die 32- und 64-Bit-Versionen. Weitere Details, insbesondere auch die unterstützten Server-Versionen, findet man auf der zugehörigen MSDN-Seite.
Das Fehlen von Windows XP in dieser Aufzählung ist für Microsoft ein weiterer logischer Schritt im Abgesang auf Windows XP, für das der Mainstream-Support bereits vor Jahren ausgelaufen ist und auch der Extended-Support in absehbarer Zeit an seine Grenzen gelangen wird. Die Wirklichkeit in Unternehmen freilich sieht häufig anders aus, und fehlende Unterstützung für Windows XP wird so manchen an der Verwendung von .NET 4.5 hindern. Der Unmut über den fehlenden Support für den beliebten Saurier unter den Betriebssystemen hat aber auch andere Gründe, die in der technischen Umsetzung des Updates von .NET 4.0 auf 4.5 liegen, auf die ich gleich noch näher eingehen möchte.
Das Update auf Version 4.5
Die Update-Strategien Microsofts für verschiedene Versionen des .NET Frameworks sind wie Schneeflocken: keine zwei sind völlig identisch. Während anfängliche Updates vollständige und isolierte Gesamtpakete waren, die seit Version 1.1 nebeneinander auf ein und demselben Rechner installiert und genutzt werden konnten, verfolgte man mit der Aktualisierung von .NET 2.0 auf die Version 3.0 einen anderen Weg: die bestehende Runtime wurde nicht angetastet; stattdessen brachte das Update “nur” Verbesserungen und Erweiterungen der Bibliotheken mit, nämlich beispielsweise WPF, WCF und die Workflow Foundation. Fortan nutzte man also die bestehende CLR 2.0 auch mit neueren Versionen des .NET Frameworks weiter. Gleichzeitig war der “side by side”-Betrieb nicht mehr möglich: .NET 3.0 ersetzte 2.0, und die Version 3.5 ersetzte 3.0. Dieses Konstrukt führte teils zu Verwirrung, weil an jenen Stellen, an denen es um die Version der Laufzeitumgebung ging, nirgends ein .NET 3.0/3.5 zu finden war, sondern nur Version 2.0 – auch wenn die Benennung oft anderes suggerierte (hier am berüchtigten Beispiel der Internet Information Services):
Im Jahre 2010 bescherte uns .NET 4 dann das vorläufige Ende dieses Layering-Prinzips und brachte neben seiner eigenen aktualisierten Runtime auch wieder die “side by side”-Installation, was sich ebenfalls im obigen Screenshot ablesen lässt: Version 2.0 und 4.0 der CLR koexistieren nebeneinander auf demselben Rechner. Das Verhältnis von .NET Framework zur verwendeten Version der Runtime ist im folgenden Diagramm dargestellt:
(Abbildung aus der MSDN-Dokumentation und © Microsoft)
Mit .NET 4.5 fügt Microsoft eine weitere Variante zu diesem bunten Strauß von Möglichkeiten hinzu: zwar bringt die neue Version wie der obigen Abbildung zu entnehmen eigentlich eine neue Runtime (CLR 4.5) mit, stellt aber trotzdem ein In-Place-Update für die Version 4.0 dar. Das heißt: Version 4.5 ersetzt seinen Vorgänger komplett, und damit können das .NET Framework 4.0 und 4.5 auch nicht nebeneinander auf demselben Rechner existieren. Die neue Version trägt dabei technisch betrachtet aber dieselbe Versionsnummer wie sein Vorgänger, nämlich 4.0.30319:
Vergeblich sucht man Verzeichnisse für .NET 4.5. Lediglich die Build-Nummer der einzelnen Assemblies weist darauf hin, dass es sich tatsächlich um das .NET Framework 4.5 handelt, denn diese wurde auf 17929 erhöht (.NET 4.0 verwendet 261):
Trotz dieses Vorgehens bedeutet das für Entwickler zunächst einmal keine Einschränkung. Über den bekannten Mechanismus der Reference Assemblies bleibt weiterhin auch die gezielte Entwicklung für ältere Versionen des Frameworks möglich, ohne dass man z.B. versehentlich Typen verwendet, die nur in .NET 4.5 zur Verfügung stehen würden. So bietet Visual Studio 2012 als Target Framework natürlich auch weiterhin die Version 4.0 an, auch wenn diese gar nicht mehr physikalisch vorhanden ist:
Ein Wort der Warnung
Der Knackpunkt, an dem sich aktuell viele Diskussionen entzünden, ist die Rückwärtskompatibilität zu .NET 4.0. Microsoft hat zwar einen enormen Aufwand betrieben, um diese Kompatibilität sicherzustellen und hunderte bestehende Anwendungen auf Binär-, Quelltext- und Serialisierungs-Kompatibilität überprüft (vgl. auch diesen Blog-Post). Dennoch sind natürlich diverse Inkompatibilitäten durchgeschlüpft und führen potenziell zu Problemen: Breaking Changes in .NET 4.5. Es handelt sich hierbei aber nicht nur um Bugs oder Seiteneffekte, sondern auch um diverse behobene Fehler, die sich in .NET 4.0 auch mit den allerneuesten Updates noch finden.
Im Umkehrschluss ergibt das durchaus problematische Konstellationen: ein Entwickler, der auf seinem Rechner mit installiertem .NET 4.5 eine Anwendung für .NET 4.0 entwickelt, kann gar nicht sicherstellen, dass sich diese Anwendung auf Zielrechnern, die nur ein “echtes” .NET 4.0 (kein .NET 4.5) installiert haben, identisch und damit fehlerfrei verhält. Eventuell ist auf seinem Rechner mit .NET 4.5 implizit ein Bugfix hinzugekommen, den es auf den .NET 4.0-Rechnern seiner Kunden gar nicht gibt.
Dies ist die Problematik, die auch im Zusammenhang mit Windows XP von vielen angekreidet wird: müssen z.B. in einem Unternehmen parallel auch noch Anwendungen für XP-Clients und oder aus anderen Gründen für reines .NET 4.0 weiterentwickelt und ausgeliefert werden, dürfen streng genommen Entwickler ihre Rechner und Build-Server gar nicht auf .NET 4.5 aktualisieren, da sonst ggfs. Fehler oder unerwünschtes Verhalten eventuell nicht entdeckt werden können. Alternativ muss dies mit zusätzlicher Test- und Entwickler-Infrastruktur abgefangen werden, was natürlich entsprechenden Aufwand und Kosten verursacht. Dementsprechend aggressiv ist die Berichterstattung momentan zu diesem Thema, und nicht selten wirft man Microsoft vor, dieselben Fehler wie bei .NET 2.0/3.0/3.5 zu begehen (ein weiterführender Artikel über die Thematik von Michael Campbell findet sich hier).
Laufzeitprobleme
Wenn sich .NET 4.5 präsentiert wie .NET 4.0, gilt dann nicht auch umgekehrt, dass eine .NET 4.5 Assembly genauso aussieht wie eine .NET 4.0 Assembly? Kann ein installiertes .NET 4.0 Framework eine .NET 4.5 Assembly ausführen? Es kann. Tatsächlich ist es so, dass dann erst zur Laufzeit, sobald die Assembly ein Feature nutzen möchte, dass nicht im “echten” .NET 4.0 vorhanden ist, eine Exception ausgelöst wird. Nutzt die .NET 4.5 Assembly nie irgendwelche der neuen Features, wird der Benutzer den Unterschied gar nicht bemerken.
Um diese Problematik zu entschärfen, wird in der Konfigurationsdatei einer neu erstellten .NET 4.5-Anwendung von Visual Studio automatisch die erforderliche .NET-Version festgehalten – nicht über die Versionsnummer, sondern über den “sku”-Eintrag:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
In diesem Fall wird schon beim Starten der Anwendung ein Hinweis angezeigt, dass mindestens .NET 4.5 benötigt wird um fortzufahren, falls dieses nicht installiert ist. Für Webanwendungen kann eine ähnliche Konfiguration über das “targetFramework”-Attribut des “compilation”-Knoten erfolgen. Dieses muss auf den Wert “4.5” gesetzt werden, um beim Starten der Anwendung einen Yellow Screen of Death auszulösen, falls .NET 4.5 auf dem Server fehlt.
Diese Ansätze lösen freilich nicht ähnliche Probleme mit externen Komponenten in falscher Version, die zu einem Projekt hinzureferenziert werden. Der Entwickler selbst kann programmatisch nur über weiche Workarounds (Diskussion) feststellen, in welcher .NET-Umgebung sein Code ausgeführt wird (um beispielsweise entsprechende Fälle selbst abzufangen), da natürlich die eingebauten Mechanismen zur Abfrage (“Environment.Version”) ebenfalls ein .NET 4.0 vorgaukeln.
Weitere Probleme
Ein nicht zu unterschätzendes Problem, auf das wir in auch in unseren Projekten beim Wechsel auf .NET 4.5 gestoßen sind, tritt bei der Verwendung des Test-Frameworks Moles auf. Tatsächlich ist es so, dass Moles selbst nicht mehr weiterentwickelt wird. Mit Visual Studio 2012 tritt der Nachfolger Microsoft Fakes auf den Plan und löst den bereits mächtigen Vorgänger ab. Naturgemäß empfiehlt Microsoft jedem die Migration zu diesem neuen Framework, bietet momentan selbst aber noch keinen Migration Guide an. Aber auch wenn der Wechsel nicht übermäßige Änderungen am Code erfordert, so kann der Aufwand doch dramatisch werden, wenn es sich um Dutzende von Testprojekten und hunderte von Tests handelt. Außerdem erfordert Fakes zwingend Visual Studio 2012 in der Ultimate-Version – der Einsatz verbietet sich daher bei vielen alleine aus finanziellen Gründen.
(Für Fakes wird leider eine Ultimate Edition benötigt, wo bei Moles noch Premium genügte)
Die Weiterverwendung von Moles nach der Installation von .NET 4.5 hingegen ist problematisch. Moles versucht, seine gefakten Typen auch für die neuen Klassen in .NET 4.5 zu erzeugen, was sich dann beim Kompilieren für .NET 4.0 in einem Fehler -1007 niederschlägt. Pikant ist, dass von dem Problem auch Visual Studio 2010 betroffen ist. Man kann sich also auch nicht durch die Verwendung des Vorgängers von Visual Studio 2012 behelfen und sitzt in der Klemme, sobald man einen Rechner auf .NET 4.5 aktualisiert hat. Ein kurzer Troubleshooting Guide auf der Internetseite von Moles versucht einen Workaround für die Probleme zu beschreiben, der nach unserer Erfahrung aber in den meisten Fällen so momentan nicht funktioniert bzw. die Problematik nicht vollständig lösen kann.
Fazit und Empfehlung
Zweifelsohne finden sich in .NET 4.5 einige äußerst interessante Neuerungen, die wir im Laufe der nächsten Wochen im Detail kennenlernen werden. Nicht nur Entwickler von Windows-8-Anwendungen, für die zwingend Visual Studio 2012 und damit automatisch auch .NET 4.5 erforderlich ist, sondern auch Entwickler ganz gewöhnlicher Desktop-Anwendungen können von diesen neuen Features profitieren.
Allerdings ist bei der Umstellung Vorsicht geboten. Man sollte sich genau überlegen, ob man z.B. noch Software für reine .NET 4.0-Umfelder pflegen und erstellen muss, und ggfs. die Liste der Inkompatibilitäten genauestens durcharbeiten, sowie die Umstellung des gesamten Teams erst nach ausführlichen Tests vornehmen. Ebenso problematisch kann eine größere Code-Basis mit dem Testing-Framework Moles sein, die einige manuelle Nacharbeit für die Migration zu Fakes oder gar einem anderen Testing-Framework erfordert.