TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.74K subscribers
Post #3252 1.5K
День 2715. #ЧтоНовенького #NET11
Закрытые Иерархии Классов. Начало

Закрытая иерархия классов может быть определена только в рамках одной сборки. Попытка создания производного класса от закрытого класса из другой сборки приведёт к ошибке компиляции.

Пусть у нас есть иерархия классов в одной сборке:
// Закрытый базовый класс 
public closed class Animal { }

// Все наследуют от закрытого класса
public class Dog : Animal { }
public class Cat : Animal { }
public class Horse : Animal { }

Здесь обычное наследование C#, ключевое слово closed никак не влияет.
Разница ощущается, если попробовать наследовать от Animal из другой сборки. Этот выдаст ошибку компиляции:
error CS9382: '…' cannot use a closed type 'Animal' from another assembly as a base type. (класс не может использовать закрытый тип 'Animal' из другой сборки в качестве базового типа).

Такой подход позволяет иметь публичный базовый тип, но при этом гарантировать, что никто, кроме вас, не сможет определять производные от него типы. Это может быть полезно для моделирования определённых предметных областей и значительно упростить логику.

Ведь это можно было сделать с помощью приватных конструкторов?
Имея приватный защищенный (private protected) или внутренний (internal) конструктор по умолчанию в базовом классе, практически невозможно создать производный тип. Вы получали ошибку CS0122 или CS1729 о невозможности использования конструктора.

Использование closed явно семантически чище. Но кроме того, в подходе с приватным конструктором компилятор на самом деле «не знал», что нельзя создавать производные типы, потому что теоретически это не исключено, даже если невозможно на практике.

С ключевым словом closed, когда компилятор собирает сборку, он точно знает все производные типы есть у закрытого класса. Теперь компилятор может применять проверку исчерпываемости к выражениям switch.

Допустим, у нас есть «обычная» иерархия классов, похожая на показанную выше, но на этот раз с использованием abstract вместо closed. Мы можем определить следующий метод:
static string Speak(Animal animal) => animal switch
{
Dog => "Гав",
Cat => "Мяу",
Horse => "Игого",
};

Но мы получим предупреждение CS8509, что выражение switch не охватывает все возможные значения, и вынуждены будем добавить вариант «по умолчанию» (catch-all), типа _ => …. Даже если вы обрабатываете все типы, компилятор об этом не знает. С его точки зрения, вы можете создать производный от Animal тип в другой сборке и передать его методу.

Использование закрытого типа означает, что компилятор знает, что это все реализации, и больше их быть не может. Т.е. он может корректно применять проверку исчерпываемости к выражениям switch, использующим закрытые типы. Более того, при добавлении нового класса, мы получим предупреждение во всех местах, где выражения switch не охватывают все случаи.

В целом это изменение означает, что модификация закрытой иерархии, как правило, безопаснее, чем модификация стандартной иерархии, поскольку компилятор способен выявлять необработанные случаи.

Заметьте, что это более «функциональный» подход, в котором данные (классы Animal) отделены от методов (Speak()). В ООП метод Speak, скорее всего, был бы определен непосредственно в иерархии типов Animal.

Окончание следует…

Источник:
https://andrewlock.net/exploring-the-dotnet-11-preview-4-closed-class-hierarchies/
  • 👍 12
More from @netdeveloperdiary
  1. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  2. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
  3. Sep 24, 2026День 2794. #Оффтоп #Здоровье Сегодня будет необычный пост. Завтра в Москве стартует конфер…
  4. Sep 23, 2026День 2793. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  5. Sep 22, 2026День 2792. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  6. Sep 21, 2026🔍Тестовое собеседование с Senior C# разработчиком уже завтра 22 сентября(уже завтра!) в 1…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →