Vor nicht allzu langer Zeit, genau genommen Ende September 2019, hat Microsoft die lange angekündigte, finale Version des .Net Core 3.0 - Frameworks veröffentlicht. Im Zuge dieser Aktion wurde auch ein neuer C#-Compiler präsentiert, welcher die neue Sprachversion C# 8.0 unterstützt. Diese bietet Programmierern einige neue Funktionen, welche zum Teil auch innerhalb des klassischen .NET - Frameworks verwendet werden können.
Neuerungen für alle .NET-Frameworks
Eine der wichtigsten Neuerungen,
die Einführung nicht-nullbarer Referenztypen
(non-nullable reference types), hat mein Kollege Michael Zöhling bereits im
Februar in einem beachtenswerten Blogartikel ausführlich diskutiert. Diese
Funktionalität ist jetzt verfügbar und erlaubt eine striktere Handhabung mit
Referenztypen. Dabei wird eine (mögliche) null-Zuweisung zu einer
Referenztypvariable nicht per se verboten, sondern führt zu einer Warnung. Zur Steuerung
dieser Warnungen wurde die Sprache um zusätzliche Context-Arten erweitert. So
führt z.B. eine null-Zuweisung unter dem Nullable-Context
zu einer Warnung, wenn die Variable nicht durch den schon von nullbaren
Wertetypen bekannten ?-Operator als nullbar definiert wurde:
Diese Funktion soll dabei helfen,
die Gefahr von NullReferenceExceptions zu verringern und kann auf Projekt-, Datei-
oder, wie oben zu sehen, auf Codeebene definiert werden.
Aufgrund der hohen Popularität
und Mächtigkeit der Kombination von Switch-Anweisungen und Patterns, welche unter
C# 7.0 relativ schwer zu schreiben sein können, wurden nun Switch-Anweisungen (switch expressions) eingeführt, welche beide
Funktionalitäten in einer einfachen Form kombinieren. Dabei handelt es sich um Methoden,
welche nur aus einer Switch-Anweisung bestehen und dadurch die Lambda-Mechanik
verwenden können. Die obligatorischen break-Befehle entfallen:
Über die obenstehende Mechanik
können auch kompliziertere Pattern benutzt werden, die in den switch-cases z.B.
mehrere Properties eines übergebenen Objekts überprüfen.
Zusätzlich wurden einige eher
kleinere zusätzliche Funktionen und Hilfestellungen dem von allen .NET-Framwork-Versionen
nutzbaren Teil der neuen C#-Version mitgegeben.
Zu Ersterem zählt zum Beispiel
die Tatsache, dass nun auch statische lokale
Funktion (static local functions), d.h. statische Funktionen als Teil
anderer Funktionen, etabliert werden können. Anders als die schon bekannten
nicht-statische lokalen Funktionen, haben diese allerdings keinen Zugriff auf
Variablen der umgebenden Funktion.
Zu Zweiterem gehört z.B. die
Vereinfachung der using-Anweisung,
welche nun keinen eigenen Block mehr benötigt, sondern ab der Verwendung bis zum
Ende des sie umgebenden Blocks gilt. Ebenso wurde die Benutzung von Verbatim-Strings in Kombination mit dem
$-Operator vereinfacht. Hier können ab sofort beide Kombinationen (sowohl
$@“string“ als auch @$“string“) verwendet werden.
Neuerungen für .NET Core 3.0 und .NET Standard 2.1
Einige Funktionen bleiben den
Benutzern des ‚normalen‘ .NET-Frameworks verschlossen. Für diese muss .NET Core
3.0 oder .NET Standard 2.1 verwendet werden.
Zu den Bemerkenswerten dieser Funktionen
gehört unter anderem die nun mögliche Erstellung asynchroner Streams (asynchronous streams). Diese verwenden das
Interface IAsyncEnumerable<T> und können mithilfe der neunen Mechanik der
await foreach – Schleife verwendet
werden. In dem folgenden, von der C#-Dokumentation inspirierten Beispiel
erzeugt eine asynchrone Funktion alle 100ms eine Zahl, welche über yield return
zurückgegeben wird. Eine await foreach-Schleife durchlauft die zurückgegebene
Collection:
Ebenfalls neu für .NET-Core und
.Net-Standard ist die Möglichkeit, in Schnittstellen
eine Standardimplementierung einzelner Methoden (default interface methods) zu
definieren. Dies wurde von Microsoft explizit eingefügt, um Schnittstellen nachträglich
zu erweitern, ohne dass bestehende Klassen angepasst werden müssen. So ist es jetzt möglich, in Interfaces definierten
Methoden eine eigene Standardlogik mitzugeben, welche in dem Fall, dass die
implementierende Klasse diese nicht überschreibt, ausgeführt wird. Allerdings ist diese nur
zugänglich, wenn der Variablentyp vom Typ des Interfaces ist. Des weiteren sind
nun auch die Implementierung von statischen
Membern und die Verwendung von Zugriffsmodifikatoren in Interfaces erlaubt.
Zusätzlich zu den hier vorgestellten
wichtigen neuen Funktionen gibt es noch weitere kleine, neue Helfer und
Veränderungen. Die vollständige Liste kann hier in der C#-Dokumentation
gefunden werden.
Wer mehr über die vielen
Möglichkeiten von C# und den neuen Sprachfeatures erfahren möchte, kann auch
hier einen passenden Kurs dazu buchen.