<?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>Pattern-Matching | The .NET Blog</title><link>https://thedotnetblog.com/ru/tags/pattern-matching/</link><description>Articles, tutorials and insights from the .NET community.</description><generator>Hugo</generator><language>ru</language><managingEditor>@thedotnetblog (The .NET Blog)</managingEditor><webMaster>@thedotnetblog</webMaster><lastBuildDate>Sun, 05 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://thedotnetblog.com/ru/tags/pattern-matching/index.xml" rel="self" type="application/rss+xml"/><item><title>C# 15 получает типы-объединения — и это именно то, что мы просили</title><link>https://thedotnetblog.com/ru/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/ru/news/emiliano-montesdeoca/csharp-15-union-types-exhaustive-matching/</guid><description>C# 15 вводит ключевое слово union — размеченные объединения с исчерпывающим сопоставлением с образцом, контролируемым компилятором. Вот как они выглядят, почему это важно и как попробовать их уже сегодня.</description><content:encoded>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Этот пост был переведён автоматически. Оригинальную версию можно найти &lt;a href="https://thedotnetblog.com/ru/news/emiliano-montesdeoca/csharp-15-union-types-exhaustive-matching/"&gt;здесь&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Это та самая фича, которую я ждал. C# 15 вводит ключевое слово &lt;code&gt;union&lt;/code&gt; — настоящие размеченные объединения с исчерпывающим сопоставлением с образцом, контролируемым компилятором. Если вы когда-нибудь завидовали размеченным объединениям F# или enum в Rust, вы точно знаете, почему это важно.&lt;/p&gt;
&lt;p&gt;Билл Вагнер &lt;a href="https://devblogs.microsoft.com/dotnet/csharp-15-union-types/"&gt;опубликовал подробный разбор&lt;/a&gt; в блоге .NET, и честно? Дизайн чистый, практичный и очень в духе C#. Давайте я покажу, что тут на самом деле есть и почему это более значимо, чем может показаться на первый взгляд.&lt;/p&gt;
&lt;h2 id="проблема-которую-решают-объединения"&gt;Проблема, которую решают объединения&lt;/h2&gt;
&lt;p&gt;До C# 15 возврат «одного из нескольких возможных типов» из метода всегда был компромиссом:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;object&lt;/code&gt;&lt;/strong&gt; — никаких ограничений, никакой помощи от компилятора, защитное приведение типов повсюду&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Маркерные интерфейсы&lt;/strong&gt; — лучше, но любой может их реализовать. Компилятор никогда не может считать набор полным&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Абстрактные базовые классы&lt;/strong&gt; — та же проблема, плюс типам нужен общий предок&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ничто из этого не даёт того, что действительно нужно: замкнутого набора типов, где компилятор гарантирует, что вы обработали каждый случай. Именно это делают типы-объединения.&lt;/p&gt;
&lt;h2 id="синтаксис-красиво-прост"&gt;Синтаксис красиво прост&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;Одна строка. &lt;code&gt;Pet&lt;/code&gt; может содержать &lt;code&gt;Cat&lt;/code&gt;, &lt;code&gt;Dog&lt;/code&gt; или &lt;code&gt;Bird&lt;/code&gt;. Неявные преобразования генерируются автоматически:&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;А вот и магия — компилятор обеспечивает исчерпывающее сопоставление:&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;Дискард &lt;code&gt;_&lt;/code&gt; не нужен. Компилятор знает, что этот switch покрывает все возможные случаи. Если позже вы добавите четвёртый тип в объединение, каждое выражение switch, которое его не обрабатывает, выдаст предупреждение. Пропущенные случаи обнаруживаются на этапе сборки, а не в рантайме.&lt;/p&gt;
&lt;h2 id="где-это-становится-практичным"&gt;Где это становится практичным&lt;/h2&gt;
&lt;p&gt;Пример с &lt;code&gt;Pet&lt;/code&gt; милый, но вот где объединения действительно сияют в реальном коде.&lt;/p&gt;
&lt;h3 id="api-ответы-возвращающие-разные-формы"&gt;API-ответы, возвращающие разные формы&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;Теперь каждый потребитель вынужден обрабатывать успех, ошибку и ошибку валидации. Больше никаких багов «забыл проверить случай ошибки».&lt;/p&gt;
&lt;h3 id="одно-значение-или-коллекция"&gt;Одно значение или коллекция&lt;/h3&gt;
&lt;p&gt;Паттерн &lt;code&gt;OneOrMore&amp;lt;T&amp;gt;&lt;/code&gt; показывает, как объединения могут иметь тело со вспомогательными методами:&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;Вызывающий код передаёт удобную форму:&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="композиция-несвязанных-типов"&gt;Композиция несвязанных типов&lt;/h3&gt;
&lt;p&gt;Это убойная фича по сравнению с традиционными иерархиями. Можно объединять типы, не имеющие ничего общего — &lt;code&gt;string&lt;/code&gt; и &lt;code&gt;Exception&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt; и &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt;. Общий предок не нужен.&lt;/p&gt;
&lt;h2 id="пользовательские-объединения-для-существующих-библиотек"&gt;Пользовательские объединения для существующих библиотек&lt;/h2&gt;
&lt;p&gt;Вот умное решение в дизайне: любой класс или struct с атрибутом &lt;code&gt;[Union]&lt;/code&gt; распознаётся как тип-объединение, если он следует базовому паттерну (публичные конструкторы для типов-случаев и свойство &lt;code&gt;Value&lt;/code&gt;). Библиотеки вроде OneOf, которые уже предоставляют типы, похожие на объединения, могут подключить поддержку компилятора без переписывания внутренней реализации.&lt;/p&gt;
&lt;p&gt;Для чувствительных к производительности сценариев с типами-значениями библиотеки могут реализовать паттерн доступа без boxing через методы &lt;code&gt;HasValue&lt;/code&gt; и &lt;code&gt;TryGetValue&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="общая-картина"&gt;Общая картина&lt;/h2&gt;
&lt;p&gt;Типы-объединения — часть более широкой истории исчерпывающей проверки в C#:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Типы-объединения&lt;/strong&gt; — исчерпывающее сопоставление по замкнутому набору типов (доступно сейчас в preview)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Закрытые иерархии&lt;/strong&gt; — модификатор &lt;code&gt;closed&lt;/code&gt; предотвращает создание производных классов вне определяющей сборки (предложено)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Закрытые enum&lt;/strong&gt; — предотвращает создание значений, отличных от объявленных членов (предложено)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Вместе эти три фичи дадут C# одну из самых полных систем типобезопасного сопоставления с образцом среди всех мейнстримных языков.&lt;/p&gt;
&lt;h2 id="попробуйте-сегодня"&gt;Попробуйте сегодня&lt;/h2&gt;
&lt;p&gt;Типы-объединения доступны в .NET 11 Preview 2:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Установите &lt;a href="https://dotnet.microsoft.com/download/dotnet"&gt;.NET 11 Preview SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Укажите &lt;code&gt;net11.0&lt;/code&gt; в качестве целевой платформы проекта&lt;/li&gt;
&lt;li&gt;Установите &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;Одно замечание: в Preview 2 вам нужно объявить &lt;code&gt;UnionAttribute&lt;/code&gt; и &lt;code&gt;IUnion&lt;/code&gt; в проекте, так как их ещё нет в рантайме. Возьмите &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; из репозитория документации, или добавьте это:&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="подводя-итог"&gt;Подводя итог&lt;/h2&gt;
&lt;p&gt;Типы-объединения — одна из тех фич, которые заставляют задуматься, как мы обходились без них. Исчерпывающее сопоставление, контролируемое компилятором, чистый синтаксис, поддержка дженериков и интеграция с существующим pattern matching — это всё, что мы просили, реализованное в стиле C#.&lt;/p&gt;
&lt;p&gt;Попробуйте их в .NET 11 Preview 2, ломайте вещи и &lt;a href="https://github.com/dotnet/csharplang/discussions/9663"&gt;делитесь обратной связью на GitHub&lt;/a&gt;. Это preview, и команда C# активно слушает. Ваши граничные случаи и отзывы о дизайне повлияют на финальный релиз.&lt;/p&gt;
&lt;p&gt;Полную языковую справку смотрите в &lt;a href="https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/union"&gt;документации по типам-объединениям&lt;/a&gt; и &lt;a href="https://learn.microsoft.com/dotnet/csharp/language-reference/proposals/unions"&gt;спецификации фичи&lt;/a&gt;.&lt;/p&gt;</content:encoded></item></channel></rss>