Heise 16.04.2026
09:00 Uhr

.NET 11.0 Preview 3 bringt Union Types und erweitert File-based Apps


Die dritte Vorschauversion von .NET 11.0 macht die lang ersehnten Union Types in C# praktisch einsetzbar, weil nun auch die IDE Visual Studio mitspielt.

.NET 11.0 Preview 3 bringt Union Types und erweitert File-based Apps

Microsoft hat .NET-Version 11.0 Preview 3 zusammen mit Visual Studio 2026 Insiders Version 11709.129 veröffentlicht. .NET 11.0 umfasst die Sprachversion 15.0 der Programmiersprache C#.

Eine Discriminated Union (oft auch Tagged Union, Algebraic Data Type oder Sum Type genannt) ist ein Datentyp, der genau einen von mehreren möglichen Typen enthalten kann, wobei jederzeit klar ist, welcher Typ gerade enthalten ist. Viele moderne Sprachen, wie F#, Rust, Swift oder TypeScript beherrschen dieses Konzept, andere wie Kotlin erlauben die Nachbildung. In C# musste man sich bisher mit dem Basistyp System.Object, Vererbung, Interfaces, Pattern Matching oder Umsetzungen auf Basis generischer Typen wie der Bibliothek OneOf behelfen.

Einen Union Type in C# 15.0 erstellen Entwicklerinnen und Entwickler mit dem neuen C#-Schlüsselwort union unter Angabe eines Namens und von einem oder mehreren Typen, beispielsweise

Dabei müssen die angegebenen Typen keinerlei Gemeinsamkeiten besitzen: Weder eine Basisklasse noch eine Schnittstelle müssen sie teilen. Das Schlüsselwort null darf man nicht als Typ angeben. Nullable Values Types (z.B. int?) und Nullable Reference Types (Person?) sind aber erlaubt.

Einer Variablen des Typs UnionName kann man dann sowohl Instanzen von Typ1 und Typ2 als auch Typ3 sowie gegebenenfalls null zuweisen. Jede andere Objekttypzuweisung wird aber verhindert.

Mit dem Operator is oder Pattern Matching lässt sich abfragen, welchen konkreten Typ die Union-Typvariable enthält. Während beim Pattern Matching automatisch ein Casting auf den Zieltyp erfolgt, muss man ohne Pattern Matching die Eigenschaft Value nutzen, um an den konkreten Typ zu kommen. Allerdings liefert Value den Typ System.Object, sodass wieder ein Casting erforderlich wird.

Als Beispiel soll ein typischer Einsatzfall für Discriminated Unions dienen: Eine Operation der Geschäftslogik kann neben einem konkreten Ergebnisobjekt mit Zeichenketten, Zahlen oder Exception-Objekten verschiedene Fehlerfälle signalisieren. Beim Einsatz von switch-Ausdrücken warnt der Compiler, wenn der Block nicht alle Fälle abfragt, mit der Warnung CS8509: „The switch expression does not handle all possible values of its input type (it is not exhaustive).“

Union Types haben das Potenzial, in einigen Teilen der .NET-Anwendungsframeworks für Vereinfachungen zu sorgen, beispielsweise bei WebAPI-Operationen mit Typed Results. Aktuell ist dies noch nicht möglich, aber es steht auf der Roadmap für ASP.NET WebAPIs und ASP.NET Core SignalR sowie Blazor zur Realisierung bis Jahresende 2026.

Folgender Code zeigt einen C# 15.0 Union Type für differenzierte Rückgabetypen einer Geschäftslogikmethode:

Eine erste Unterstützung für Union Types gab es in Preview 2 von .NET 11.0 im März. Allerdings hatte Microsoft dieses Feature in dem Blogeintrag vergessen zu erwähnen. In den Release Notes zu .NET 11.0 Preview 2 führte der C#-Link ins Nirvana. Anfang April gab es dann einen Blogeintrag, der nachlieferte, dass Union Types in Preview 2 schon möglich waren, allerdings ohne Editor-Unterstützung. Der Editor funktioniert nun für Union Types in der Visual Studio-Version 2026 Insiders 11709.129.

Allerdings fehlt auch in Preview 3 immer noch ein Stück Code in der Basisklassenbibliothek. Neben dem Tag <LangVersion>preview</LangVersion> in der Projektdatei müssen Entwicklerinnen und Entwickler daher auch den Inhalt des folgenden Listings mit der Implementierung der Annotation [Union] via Klasse UnionAttribute in jedes Projekt aufnehmen, das Union Types nutzen will:

Hintergrund ist, dass der C# 15.0-Compiler alle Union Types automatisch mit der Annotation [Union] versieht. Das erkennt man, wenn man den Union Type mit ILSpy dekompiliert:

In .NET 11.0 Preview 1 hatte Microsoft die Komprimierung mit Zstandard als Alternative zu Deflate, GZip und Brotli eingeführt. In Preview 3 ist diese Implementierung nun Teil der System.IO.Compression.dll und nicht mehr der eigenständigen System.IO.Compression.Zstandard.dll. Zudem gibt es nun eine CRC32-Prüfung der Einträge, sodass fehlerhafte Archive schnell auffallen. In ASP.NET Core lässt sich Zstandard nun für die Komprimierung für HTTP verwenden. Das erfordert aber eine manuelle Aktivierung:

Im Objekt-relationalen Mapper Entity Framework Core gibt es eine neue Methode GetEntriesForState() in der Klasse ChangeTracker. Hiermit kann man sich alle Objekte liefern lassen, die sich in bestimmten Zuständen (Added, Modified, Deleted, Unchanged) befinden, beispielsweise

Im Gegensatz zu der vorher schon verfügbaren Operation Entries(), die diese Informationen ebenfalls bereitstellt, ruft GetEntriesForState() nicht vorher die Methode DetectChanges() auf, die in gut gefüllten Kontextinstanzen die Performance drücken kann.

In .NET MAUI gibt es nun einen LongPressGestureRecognizer, um auf längeres Drücken zu reagieren. Dabei kann man die Mindestdauer in Millisekunden angeben, ab wann die Geste als „lang“ gelten soll:

Auch das Landkartensteuerelement <Map> wurde in .NET MAUI 11.0 Preview 3 verbessert.

Laut Release Notes soll man nun Projektmappenfilter-Dateien nicht nur über Visual Studio, sondern auch per Kommandozeile erstellen können. Microsoft liefert dazu in den Release Notes diesen Kommandozeilencode:

Im Schnelltest zeigte sich aber, dass hier die Implementierung anders ist, als die Release Notes es anzeigen, denn

legt eine Datei mit doppelter Dateinamenserweiterung an: MyApp.slnf.slnf. Man muss hier also die Dateinamenserweiterung weglassen, bei den Folgebefehlen muss sie aber stehen. Zudem funktioniert das Microsoft-Beispiel nur, wenn der Filter genau heißen soll wie die Projektmappendatei selbst, nur mit .slnf statt .slnx.

Folgender Code zeigt eine funktionierende Umsetzung mit abweichendem Namen:

In .NET 10.0 hatte Microsoft sogenannte File-based Apps eingeführt, mit denen man C#-Programmcode in einer einzelnen Quellcodedatei direkt ohne Projektmappe und ohne vorheriges Kompilieren ausführen kann. In .NET 11.0 Preview 3 kommt die Erweiterung dieses Features um Include-Dateien. Damit kann man in einer C#-Datei andere Dateien über das neue Konstrukt #:include einbinden:

Dafür benötigt man aktuell zusätzlich folgende Zeile:

Visual Studio Code Version 1.115 mit der aktuellen C# Dev Kit Version 3.11.200 meldet, dass der Editor das Feature noch nicht kennt:

Beim Anlegen einer Datenbankschemamigration mit Add-Migration beziehungsweise dotnet ef migrations add speichert Entity Framework Core in der Snapshot-Datei, die den aktuellen Objektmodellzustand zum Zeitpunkt der Erstellung der Schemamigration repräsentiert, nun den Namen der aktuellen Schemamigration in einer Variablen mit dem Namen LatestMigrationId. Zudem gibt es dort einen Kommentar:

Damit ist leichter erkennbar, dass es einen Versionsverwaltungskonflikt bei den Schemamigrationen gibt.

Seit .NET 11.0 Preview 2 gibt es die asynchrone Laufzeitumgebung für .NET, die erstmals direkt async und await versteht, ohne dass der Compiler im Hintergrund eine State Machine dafür bauen muss. In Preview 3 hat Microsoft die asynchrone Laufzeitumgebung auch in Verbindung mit der direkten Erzeugung von Maschinencode mit ReadyToRun Images und Native AOT implementiert. Zudem ist die Projekteinstellung <EnablePreviewFeatures>true</EnablePreviewFeatures> nicht mehr notwendig. Um die asynchrone Laufzeitumgebung zu setzen, muss man nur noch <Features>runtime-async=on</Features> setzen.

Weitere Details finden sich in den Ankündigungen zu .NET-Version 11.0 Preview 3 und Visual Studio 2026 Insiders Version 11709.129.

.NET 11.0 soll im November 2026 erscheinen und einen Standard-Term-Support von zwei Jahren erhalten. Bis dahin ist mit vier weiteren Preview-Versionen von Mai bis August sowie jeweils einer Release-Candidate-Version im September und Oktober zu rechnen.

(rme)