<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Dotnet-11 | The .NET Blog</title><link>https://thedotnetblog.com/de/tags/dotnet-11/</link><description>Articles, tutorials and insights from the .NET community.</description><generator>Hugo</generator><language>de</language><managingEditor>@thedotnetblog (The .NET Blog)</managingEditor><webMaster>@thedotnetblog</webMaster><lastBuildDate>Thu, 16 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://thedotnetblog.com/de/tags/dotnet-11/index.xml" rel="self" type="application/rss+xml"/><item><title>Pin-Clustering landet endlich in .NET MAUI Maps — Eine Property, null Aufwand</title><link>https://thedotnetblog.com/de/news/emiliano-montesdeoca/maui-maps-pin-clustering-finally/</link><pubDate>Thu, 16 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/de/news/emiliano-montesdeoca/maui-maps-pin-clustering-finally/</guid><description>.NET MAUI 11 Preview 3 bringt natives Pin-Clustering für das Map-Control. Eine Property, separate Clustering-Gruppen und Tap-Handling — alles eingebaut.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Dieser Beitrag wurde automatisch übersetzt. Die Originalversion findest du &lt;a href="https://thedotnetblog.com/de/news/emiliano-montesdeoca/maui-maps-pin-clustering-finally/"&gt;hier&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Kennst du den Moment, wenn du eine Karte mit hundert Pins lädst und das Ganze zu einem unlesbaren Klumpen wird? Ja, so war die .NET MAUI Maps-Erfahrung bisher. Damit ist jetzt Schluss.&lt;/p&gt;
&lt;p&gt;David Ortinau &lt;a href="https://devblogs.microsoft.com/dotnet/pin-clustering-in-dotnet-maui-maps/"&gt;hat gerade angekündigt&lt;/a&gt;, dass .NET MAUI 11 Preview 3 Pin-Clustering auf Android und iOS/Mac Catalyst out of the box mitliefert. Und das Beste — es ist lächerlich einfach zu aktivieren.&lt;/p&gt;
&lt;h2 id="eine-property-sie-alle-zu-beherrschen"&gt;Eine Property, sie alle zu beherrschen&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;maps:Map&lt;/span&gt; &lt;span class="na"&gt;IsClusteringEnabled=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;True&amp;#34;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Das war&amp;rsquo;s. Benachbarte Pins werden in Clustern mit einem Zähler-Badge gruppiert. Reinzoomen — sie expandieren. Rauszoomen — sie kollabieren. Genau das Verhalten, das Nutzer von jeder modernen Karte erwarten — und jetzt bekommst du es mit einer einzigen Property.&lt;/p&gt;
&lt;h2 id="unabhängige-clustering-gruppen"&gt;Unabhängige Clustering-Gruppen&lt;/h2&gt;
&lt;p&gt;Hier wird es interessant. Nicht alle Pins sollten zusammen geclustert werden. Cafés und Parks sind verschiedene Dinge, und deine Karte sollte das wissen.&lt;/p&gt;
&lt;p&gt;Die &lt;code&gt;ClusteringIdentifier&lt;/code&gt;-Property ermöglicht es dir, Pins in unabhängige Gruppen zu trennen:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Pin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Pike Place Coffee&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;47.6097&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;122.3331&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ClusteringIdentifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;coffee&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Pin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Occidental Square&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Location&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;47.6064&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;122.3325&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ClusteringIdentifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;parks&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pins mit demselben Identifier clustern zusammen. Verschiedene Identifier bilden unabhängige Cluster, selbst wenn sie geografisch nah beieinander liegen. Kein Identifier? Standardgruppe. Sauber und vorhersehbar.&lt;/p&gt;
&lt;h2 id="cluster-taps-verarbeiten"&gt;Cluster-Taps verarbeiten&lt;/h2&gt;
&lt;p&gt;Wenn ein Nutzer auf einen Cluster tippt, bekommst du ein &lt;code&gt;ClusterClicked&lt;/code&gt;-Event mit allem, was du brauchst:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClusterClicked&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pins&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;DisplayAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;$&amp;#34;Cluster ({e.Pins.Count} pins)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;OK&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Suppress default zoom-to-cluster behavior:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// e.Handled = true;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Die Event-Args liefern dir &lt;code&gt;Pins&lt;/code&gt; (die Pins im Cluster), &lt;code&gt;Location&lt;/code&gt; (das geografische Zentrum) und &lt;code&gt;Handled&lt;/code&gt; (auf &lt;code&gt;true&lt;/code&gt; setzen, wenn du den Standard-Zoom überschreiben willst). Einfach, praktisch, genau was man erwartet.&lt;/p&gt;
&lt;h2 id="plattform-details-die-man-kennen-sollte"&gt;Plattform-Details, die man kennen sollte&lt;/h2&gt;
&lt;p&gt;Auf Android verwendet das Clustering einen eigenen Grid-basierten Algorithmus, der bei Zoom-Änderungen neu berechnet — keine externen Abhängigkeiten. Auf iOS und Mac Catalyst wird die native &lt;code&gt;MKClusterAnnotation&lt;/code&gt;-Unterstützung von MapKit genutzt, was flüssige, plattformnative Animationen bedeutet.&lt;/p&gt;
&lt;p&gt;Das ist einer dieser Fälle, in denen das MAUI-Team die richtige Entscheidung getroffen hat — auf die Plattform setzen, wo es Sinn ergibt.&lt;/p&gt;
&lt;h2 id="warum-das-wichtig-ist"&gt;Warum das wichtig ist&lt;/h2&gt;
&lt;p&gt;Pin-Clustering war eines der meistgewünschten Features in .NET MAUI (&lt;a href="https://github.com/dotnet/maui/issues/11811"&gt;Issue #11811&lt;/a&gt;), und das aus gutem Grund. Jede App, die Standorte auf einer Karte zeigt — Lieferverfolgung, Filialfinder, Immobilien — braucht das. Vorher musstest du es selbst bauen oder eine Drittanbieter-Bibliothek einbinden. Jetzt ist es eingebaut.&lt;/p&gt;
&lt;p&gt;Für uns .NET-Entwickler, die plattformübergreifende mobile Apps bauen, ist das genau die Art von Quality-of-Life-Verbesserung, die MAUI zu einer wirklich praktischen Wahl für kartenintensive Szenarien macht.&lt;/p&gt;
&lt;h2 id="loslegen"&gt;Loslegen&lt;/h2&gt;
&lt;p&gt;Installiere &lt;a href="https://dotnet.microsoft.com/download/dotnet/11.0"&gt;.NET 11 Preview 3&lt;/a&gt; und aktualisiere den .NET MAUI Workload. Das &lt;a href="https://github.com/dotnet/maui-samples/tree/main/10.0/UserInterface/Views/Map/MapDemo/WorkingWithMaps"&gt;Maps-Sample&lt;/a&gt; enthält eine neue Clustering-Seite, mit der du sofort loslegen kannst.&lt;/p&gt;
&lt;p&gt;Bau etwas damit — und lass deine Karten endlich atmen.&lt;/p&gt;</content:encoded></item><item><title>C# 15 bekommt Union Types — und sie sind genau das, was wir uns gewünscht haben</title><link>https://thedotnetblog.com/de/news/emiliano-montesdeoca/csharp-15-union-types-exhaustive-matching/</link><pubDate>Sun, 05 Apr 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/de/news/emiliano-montesdeoca/csharp-15-union-types-exhaustive-matching/</guid><description>C# 15 führt das union-Schlüsselwort ein — compiler-erzwungene diskriminierte Unions mit erschöpfendem Pattern Matching. So sehen sie aus, warum sie wichtig sind und wie man sie heute ausprobieren kann.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Dieser Beitrag wurde automatisch übersetzt. Für die Originalversion &lt;a href="https://thedotnetblog.com/de/news/emiliano-montesdeoca/csharp-15-union-types-exhaustive-matching/"&gt;klicke hier&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Das ist das Feature, auf das ich gewartet habe. C# 15 führt das &lt;code&gt;union&lt;/code&gt;-Schlüsselwort ein — echte diskriminierte Unions mit compiler-erzwungenem erschöpfendem Pattern Matching. Wenn du jemals die diskriminierten Unions von F# oder die Enums von Rust beneidet hast, weißt du genau, warum das wichtig ist.&lt;/p&gt;
&lt;p&gt;Bill Wagner hat &lt;a href="https://devblogs.microsoft.com/dotnet/csharp-15-union-types/"&gt;den Deep Dive veröffentlicht&lt;/a&gt; auf dem .NET Blog, und ehrlich? Das Design ist sauber, praktisch und sehr C#. Lass mich dir zeigen, was wirklich hier ist und warum es eine größere Sache ist, als es auf den ersten Blick scheint.&lt;/p&gt;
&lt;h2 id="das-problem-das-unions-lösen"&gt;Das Problem, das Unions lösen&lt;/h2&gt;
&lt;p&gt;Vor C# 15 war die Rückgabe von &amp;ldquo;einem von mehreren möglichen Typen&amp;rdquo; aus einer Methode immer ein Kompromiss:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;object&lt;/code&gt;&lt;/strong&gt; — keine Einschränkungen, keine Compiler-Hilfe, defensives Casting überall&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Marker-Interfaces&lt;/strong&gt; — besser, aber jeder kann sie implementieren. Der Compiler kann die Menge nie als vollständig betrachten&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Abstrakte Basisklassen&lt;/strong&gt; — gleiches Problem, plus die Typen brauchen einen gemeinsamen Vorfahren&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nichts davon gibt dir, was du eigentlich willst: eine geschlossene Menge von Typen, bei der der Compiler garantiert, dass du jeden Fall behandelt hast. Das ist es, was Union Types machen.&lt;/p&gt;
&lt;h2 id="die-syntax-ist-wunderschön-einfach"&gt;Die Syntax ist wunderschön einfach&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;class&lt;/span&gt; &lt;span class="n"&gt;Bird&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;union&lt;/span&gt; &lt;span class="n"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Bird&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Eine Zeile. &lt;code&gt;Pet&lt;/code&gt; kann eine &lt;code&gt;Cat&lt;/code&gt;, einen &lt;code&gt;Dog&lt;/code&gt; oder einen &lt;code&gt;Bird&lt;/code&gt; enthalten. Implizite Konvertierungen werden automatisch generiert:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Pet&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Rex&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Dog { Name = Rex }&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Und hier ist die Magie — der Compiler erzwingt erschöpfendes Matching:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pet&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Dog&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Cat&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Bird&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Kein Discard &lt;code&gt;_&lt;/code&gt; nötig. Der Compiler weiß, dass dieser Switch jeden möglichen Fall abdeckt. Wenn du später einen vierten Typ zur Union hinzufügst, erzeugt jeder Switch-Ausdruck, der ihn nicht behandelt, eine Warnung. Fehlende Fälle werden zur Build-Zeit erkannt, nicht zur Laufzeit.&lt;/p&gt;
&lt;h2 id="wo-das-praktisch-wird"&gt;Wo das praktisch wird&lt;/h2&gt;
&lt;p&gt;Das &lt;code&gt;Pet&lt;/code&gt;-Beispiel ist nett, aber hier glänzen Unions wirklich in echtem Code.&lt;/p&gt;
&lt;h3 id="api-antworten-die-verschiedene-formen-zurückgeben"&gt;API-Antworten, die verschiedene Formen zurückgeben&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;union&lt;/span&gt; &lt;span class="n"&gt;ApiResult&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ApiError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ValidationFailure&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Jetzt ist jeder Konsument gezwungen, Erfolg, Fehler und Validierungsfehler zu behandeln. Keine &amp;ldquo;Ich habe vergessen, den Fehlerfall zu prüfen&amp;rdquo;-Bugs mehr.&lt;/p&gt;
&lt;h3 id="einzelwert-oder-collection"&gt;Einzelwert oder Collection&lt;/h3&gt;
&lt;p&gt;Das &lt;code&gt;OneOrMore&amp;lt;T&amp;gt;&lt;/code&gt;-Muster zeigt, wie Unions einen Body mit Hilfsmethoden haben können:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;union&lt;/span&gt; &lt;span class="n"&gt;OneOrMore&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AsEnumerable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;single&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;single&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;multiple&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;multiple&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Aufrufer übergeben die Form, die ihnen passt:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;OneOrMore&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;dotnet&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;OneOrMore&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;moreTags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;csharp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;unions&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;preview&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsEnumerable&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$&amp;#34;[{tag}] &amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// [dotnet]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="unrelated-typen-zusammensetzen"&gt;Unrelated Typen zusammensetzen&lt;/h3&gt;
&lt;p&gt;Das ist das Killer-Feature gegenüber traditionellen Hierarchien. Du kannst Typen vereinen, die nichts gemeinsam haben — &lt;code&gt;string&lt;/code&gt; und &lt;code&gt;Exception&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt; und &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;. Kein gemeinsamer Vorfahre nötig.&lt;/p&gt;
&lt;h2 id="custom-unions-für-bestehende-bibliotheken"&gt;Custom Unions für bestehende Bibliotheken&lt;/h2&gt;
&lt;p&gt;Hier ist eine clevere Design-Entscheidung: Jede Klasse oder Struct mit einem &lt;code&gt;[Union]&lt;/code&gt;-Attribut wird als Union-Typ erkannt, solange sie dem grundlegenden Muster folgt (öffentliche Konstruktoren für Case-Typen und eine &lt;code&gt;Value&lt;/code&gt;-Property). Bibliotheken wie OneOf, die bereits Union-ähnliche Typen bereitstellen, können sich für Compiler-Unterstützung entscheiden, ohne ihre Interna umzuschreiben.&lt;/p&gt;
&lt;p&gt;Für performance-sensitive Szenarien mit Werttypen können Bibliotheken ein Boxing-freies Zugriffsmuster mit &lt;code&gt;HasValue&lt;/code&gt;- und &lt;code&gt;TryGetValue&lt;/code&gt;-Methoden implementieren.&lt;/p&gt;
&lt;h2 id="das-große-ganze"&gt;Das große Ganze&lt;/h2&gt;
&lt;p&gt;Union Types sind Teil einer breiteren Exhaustiveness-Story, die zu C# kommt:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Union Types&lt;/strong&gt; — erschöpfendes Matching über eine geschlossene Menge von Typen (jetzt in Preview verfügbar)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Geschlossene Hierarchien&lt;/strong&gt; — der &lt;code&gt;closed&lt;/code&gt;-Modifier verhindert abgeleitete Klassen außerhalb der definierenden Assembly (vorgeschlagen)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Geschlossene Enums&lt;/strong&gt; — verhindert die Erstellung von Werten außer den deklarierten Membern (vorgeschlagen)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Zusammen werden diese drei Features C# eines der umfassendsten typsicheren Pattern-Matching-Systeme in jeder Mainstream-Sprache geben.&lt;/p&gt;
&lt;h2 id="probier-es-heute-aus"&gt;Probier es heute aus&lt;/h2&gt;
&lt;p&gt;Union Types sind in .NET 11 Preview 2 verfügbar:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Installiere das &lt;a href="https://dotnet.microsoft.com/download/dotnet"&gt;.NET 11 Preview SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Setze &lt;code&gt;net11.0&lt;/code&gt; als Target in deinem Projekt&lt;/li&gt;
&lt;li&gt;Setze &lt;code&gt;&amp;lt;LangVersion&amp;gt;preview&amp;lt;/LangVersion&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ein Hinweis: In Preview 2 musst du &lt;code&gt;UnionAttribute&lt;/code&gt; und &lt;code&gt;IUnion&lt;/code&gt; in deinem Projekt deklarieren, da sie noch nicht in der Runtime sind. Hol dir &lt;a href="https://github.com/dotnet/docs/blob/e68b5dd1e557b53c45ca43e61b013bc919619fb9/docs/csharp/language-reference/builtin-types/snippets/unions/RuntimePolyfill.cs"&gt;RuntimePolyfill.cs&lt;/a&gt; aus dem Docs-Repo, oder füge das hinzu:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;System.Runtime.CompilerServices&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="na"&gt; AllowMultiple = false)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;sealed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnionAttribute&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Attribute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IUnion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;object?&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="fazit"&gt;Fazit&lt;/h2&gt;
&lt;p&gt;Union Types sind eines dieser Features, bei denen man sich fragt, wie wir ohne sie ausgekommen sind. Compiler-erzwungenes erschöpfendes Matching, saubere Syntax, generische Unterstützung und Integration mit bestehendem Pattern Matching — es ist alles, was wir wollten, auf die C#-Art umgesetzt.&lt;/p&gt;
&lt;p&gt;Probier sie in .NET 11 Preview 2 aus, mach Sachen kaputt und &lt;a href="https://github.com/dotnet/csharplang/discussions/9663"&gt;teile dein Feedback auf GitHub&lt;/a&gt;. Das ist Preview, und das C#-Team hört aktiv zu. Deine Edge Cases und Design-Feedback werden die finale Version formen.&lt;/p&gt;
&lt;p&gt;Für die vollständige Sprachreferenz, schau dir die &lt;a href="https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/union"&gt;Union Types-Dokumentation&lt;/a&gt; und die &lt;a href="https://learn.microsoft.com/dotnet/csharp/language-reference/proposals/unions"&gt;Feature-Spezifikation&lt;/a&gt; an.&lt;/p&gt;</content:encoded></item></channel></rss>