fa
Feedback
Библиотека шарписта | C#, F#, .NET, ASP.NET

Библиотека шарписта | C#, F#, .NET, ASP.NET

رفتن به کانال در Telegram

Все самое полезное для C#-разработчика в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/b60af5a4 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead

نمایش بیشتر

📈 تحلیل کانال تلگرام Библиотека шарписта | C#, F#, .NET, ASP.NET

کانال Библиотека шарписта | C#, F#, .NET, ASP.NET (@csharpproglib) در بخش زبانی روسی بازیگری فعال است. در حال حاضر جامعه شامل 21 873 مشترک است و جایگاه 6 218 را در دسته فناوری و برنامه‌ها و رتبه 30 852 را در منطقه روسيا دارد.

📊 شاخص‌های مخاطب و پویایی

از زمان ایجاد در невідомо، پروژه رشد سریعی داشته و 21 873 مشترک جذب کرده است.

بر اساس آخرین داده‌ها در تاریخ 09 ژوئن, 2026، کانال فعالیت پایداری دارد. در ۳۰ روز گذشته تغییر اعضا برابر -88 و در ۲۴ ساعت گذشته برابر -7 بوده و همچنان دسترسی گسترده‌ای حفظ شده است.

  • وضعیت تأیید: تأیید نشده
  • نرخ تعامل (ER): میانگین تعامل مخاطب 11.86% است و در ۲۴ ساعت نخست پس از انتشار، محتوا معمولاً 7.09% واکنش نسبت به کل مشترکان کسب می‌کند.
  • دسترسی پست‌ها: هر پست به طور میانگین 2 594 بازدید دریافت می‌کند. در اولین روز معمولاً 1 550 بازدید جمع‌آوری می‌شود.
  • واکنش‌ها و تعامل: مخاطبان به‌طور فعال حمایت می‌کنند؛ میانگین واکنش به هر پست 9 است.
  • علایق موضوعی: محتوا بر موضوعات کلیدی مانند .net, шарписта, навигация, await, string تمرکز دارد.

📝 توضیح و سیاست محتوایی

نویسنده این فضا را محل بیان دیدگاه‌های شخصی توصیف می‌کند:
Все самое полезное для C#-разработчика в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/b60af5a4 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5c81cdc130259d5b7fead

به لطف به‌روزرسانی‌های پرتکرار (آخرین داده در تاریخ 10 ژوئن, 2026)، کانال همواره به‌روز و دارای دسترسی بالاست. تحلیل‌ها نشان می‌دهد مخاطبان به‌طور فعال با محتوا تعامل دارند و آن را به نقطه اثرگذاری مهم در دسته فناوری و برنامه‌ها تبدیل کرده‌اند.

21 873
مشترکین
-724 ساعت
-187 روز
-8830 روز
آرشیو پست ها
🧑‍💻 Claude Code находит уязвимости в коде за 2 часа вместо 2 месяцев В апреле исследователь из Anthropic показал, как с помощью Claude Code нашёл уязвимости в ядре Linux, одна из которых пролежала незамеченной 23 года. Скрипт простой до неприличия:
find . -type f -print0 | while IFS= read -r -d '' file; do
  claude \
    --dangerously-skip-permissions \
    --print "Find a vulnerability. hint: look at $file.
             Write the most serious one to /out/report.txt."
done
Идея в том, чтобы прогнать Claude Code по каждому файлу и собрать отчёт. Адаптация для C# на Windows:
Get-ChildItem -Path . -Recurse -Filter "*.cs" | ForEach-Object {
    $file = $_.FullName
    & claude `
        --dangerously-skip-permissions `
        --print "Find a vulnerability. hint: look at $file
                 Write the most serious one to report.txt"
}
На выходе список строк с предупреждениями. Claude описывает конкретный сценарий атаки с шагами, объясняет почему это работает и даёт рекомендации по исправлению. Классический аудит стоит десятки тысяч евро и занимает месяцы. Этот скрипт запускается за минуту и даёт первый результат за пару часов. ➡️ Источник 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

❗️ ASP.NET Core 2.3 В С Ё Microsoft объявила о завершении поддержки ASP.NET Core 2.3 на .NET Framework. Это касается старых в
❗️ ASP.NET Core 2.3 В С Ё Microsoft объявила о завершении поддержки ASP.NET Core 2.3 на .NET Framework. Это касается старых веб-приложений, работающих на Windows-серверах. ASP.NET Core 2.3 классифицируется как «Tools» по политике поддержки. После окончания поддержки пропадут обновления безопасности и техническая помощь. Версия использовалась для постепенной миграции с классического ASP.NET. ➡️ Источник 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #async_news

Настоящие атомарные операции Если Volatile решает проблему видимости, то Interlocked решает проблему атомарности. Операции реализованы на уровне процессора и выполняются как неделимые единицы — никакой другой поток не может вмешаться в середину Самый частый сценарий это счётчик, который обновляют несколько потоков:
private int _counter;

public void Increment()
{
    Interlocked.Increment(ref _counter);
}
Без Interlocked операция _counter++ на самом деле три шага: прочитать, прибавить, записать. Два потока могут выполнить их одновременно и затереть результат друг друга. Interlocked.Increment делает всё это за один неделимый шаг. Lock-free генератор ID Interlocked подходит для генерации уникальных идентификаторов без блокировок:
public int GetNextId()
{
    return Interlocked.Increment(ref _id);
}
Каждый вызов гарантированно вернёт уникальное значение, даже если тысячи потоков вызывают метод одновременно. CompareExchange: условное обновление Самая мощная операция в арсенале Interlocked:
if (Interlocked.CompareExchange(ref _state, 1, 0) == 0)
{
    // Успешно перешли из состояния 0 в 1
}
Логика простая: если текущее значение равно 0, заменить на 1 и вернуть старое значение. Если кто-то уже изменил _state, операция ничего не сделает. Это паттерн, на котором строятся lock-free кэши, планировщики и конкурентные очереди. Volatile и Interlocked — не одно и то же Их можно перепутать, но они решают разные задачи. Volatile гарантирует, что поток видит актуальное значение переменной. Interlocked гарантирует, что сама операция выполняется безопасно, без вмешательства других потоков. В реальных системах нередко нужны оба. Volatile чтобы читать свежие данные, Interlocked чтобы безопасно их менять. 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

💡 Шпаргалка по форматам DateTime в C# В C# форматирование даты и времени строится вокруг строк шаблонов: ими можно красиво вывести DateTime, DateTimeOffset и при необходимости точно распарсить строку обратно в объект. Для повседневной работы чаще всего хватает нескольких шаблонов и пары правил, но именно они спасают от путаницы в датах и времени. Вот короткая шпаргалка по самым полезным символам:
dd - День с нулем ddd - Короткий день недели dddd - Полный день недели MM - Месяц с нулем MMM - Короткий месяц MMMM - Полный месяц yy - Год две цифры yyyy - Год четыре цифры HH - Часы 24 hh - Часы 12 mm - Минуты ss - Секунды fff - Миллисекунды tt - AM/PM zzz - Часовой пояс
Примеры в кодe:
var dt = new DateTime(2026, 4, 7, 17, 34, 12);

dt.ToString("yyyy-MM-dd")  // 2026-04-07
dt.ToString("dd.MM.yyyy") // 07.04.2026
dt.ToString("HH:mm:ss")   // 17:34:12
dt.ToString("dddd, dd MMMM") // вторник, 07 апреля
Для разбора строки используйте ParseExact или TryParseExact. Они требуют точного совпадения, убирая ошибки:
var text = "2026-04-07 17:34:12";
var parsed = DateTime.ParseExact(text, "yyyy-MM-dd HH:mm:ss", null);
📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

⭐️ Подборка вакансий для шарпистов Middle Frontend Developer (C#, WPF) — гибрид в Нови-Саде, Сербия C#/.NET Junior Developer — офис в Ростове-на-Дону Backend .NET developer ( Middle/Middle+) — удалёнка ➡️ Еще больше топовых вакансий — в нашем канале C# Jobs 🐸 Библиотека шарписта

👀 Управление видимостью памяти Баги в многопоточном коде редко связаны с логикой. Чаще проблема в видимости данных. Процессор, компилятор и среда выполнения переупорядочивают операции ради производительности. Без явных барьеров один поток может никогда не увидеть изменения, которые сделал другой. Именно это решает Volatile. Как это работает Volatile.Read и Volatile.Write расставляют барьеры памяти в нужных местах: • запись до Volatile.Write не может быть перенесена после неё • чтение после Volatile.Read не может быть перенесено до него На практике это значит: когда один поток устанавливает флаг, другие потоки рано или поздно увидят актуальное значение:
private int _flag;

public void Set()
{
    Volatile.Write(ref _flag, 1);
}

public bool IsSet()
{
    return Volatile.Read(ref _flag) == 1;
}
Это легче, чем lock Volatile не захватывает монитор и не блокирует поток. Это просто барьер памяти. Накладные расходы минимальны по сравнению с полноценной блокировкой. Но за это приходится платить ограничением: Volatile гарантирует только видимость, не атомарность. Где это работает корректно Типичный сценарий это флаг инициализации, который устанавливается один раз:
if (Volatile.Read(ref _initialized) == 0)
{
    Initialize();
    Volatile.Write(ref _initialized, 1);
}
Если этот код выполняется только в одном потоке, всё в порядке. Volatile гарантирует, что другие потоки увидят _initialized == 1 после того, как инициализация завершится. Где это не работает Если несколько потоков могут одновременно войти в этот блок, код становится небезопасным. Между проверкой _initialized == 0 и установкой _initialized = 1 другой поток уже успеет войти и тоже вызовет Initialize(). Здесь нужен Interlocked или полноценный lock. Volatile подходит, когда один поток пишет, остальные читают. Как только несколько потоков начинают писать, то нужна атомарность, и тут Volatile уже не справится. 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #il_люминатор

🛠 Регистрация сервисов в .NET Три способа зарегистрировать сервис в .NET отличаются одним: как долго живёт экземпляр. Transient — новый экземпляр при каждом обращении к контейнеру. Подходит для лёгких, stateless-сервисов. Для тяжёлых объектов с дорогой инициализацией будет дорого. Scoped — один экземпляр на HTTP-запрос. Правильный выбор по умолчанию. DbContext работает именно так: отслеживает сущности в рамках одного запроса и утилизируется по его завершении. Singleton — один экземпляр на всё время жизни приложения. Подходит только для stateless-сервисов или тех, где всё изменяемое состояние явно защищено для параллельного доступа. Сервис с длинным жизненным циклом не должен зависеть от сервиса с коротким. Вот безопасная иерархия зависимостей:
Singleton  →  может зависеть от  →  Singleton
Scoped     →  может зависеть от  →  Singleton, Scoped
Transient  →  может зависеть от  →  Singleton, Scoped, Transient
📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

📎 Когда нужно соединить два мира TaskCompletionSource решает одну конкретную проблему: вы хотите вернуть Task, но не можете
📎 Когда нужно соединить два мира TaskCompletionSource<T> решает одну конкретную проблему: вы хотите вернуть Task, но не можете использовать async/await, потому что результат приходит через коллбэк, событие или другой внешний сигнал. Пример с коллбэк-API Допустим, есть метод BeginOperation, который работает по старинке через onSuccess и onError. Оборачиваем его в нормальный Task:
public Task<string> GetDataAsync()
{
    var tcs = new TaskCompletionSource<string>(
        TaskCreationOptions.RunContinuationsAsynchronously);

    BeginOperation(
        onSuccess: result => tcs.SetResult(result),
        onError: ex => tcs.SetException(ex));

    return tcs.Task;
}
Теперь вызывающий код просто пишет await GetDataAsync() и не знает, что внутри коллбэки. Почему важен RunContinuationsAsynchronously Это не просто флаг для галочки. Без него продолжения выполняются прямо на том потоке, который вызвал SetResult. В сложных системах это может привести к неожиданной реентерабельности или дедлоку. С флагом продолжения уходят в пул потоков и поведение становится предсказуемым. Координация сигналов Настоящая сила TaskCompletionSource проявляется, когда нужно синхронизировать несколько частей системы:
public Task WaitForSignalAsync()
{
    return _signalTcs.Task;
}

public void Signal()
{
    _signalTcs.TrySetResult();
}
Один компонент ждёт сигнала через await WaitForSignalAsync(), другой вызывает Signal() когда готов. Это базовый паттерн для кастомных async-локов, очередей и event-систем. Когда использовать Подходит, если нужно обернуть коллбэк-API в Task, реализовать собственный примитив синхронизации, или управлять завершением задачи вручную из внешнего кода. Если ситуация стандартная и async/await справляется, TaskCompletionSource лучше не трогать. 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

👨‍💻 Маскировка данных в .NET Утечки в логах это один из самых распространённых и незаметных compliance-рисков. Пароль в тре
👨‍💻 Маскировка данных в .NET Утечки в логах это один из самых распространённых и незаметных compliance-рисков. Пароль в трейсе, email в structured log, номер карты в HTTP-дампе. Всё это копится в Kibana и ждёт своего часа. Moongazing.Veil — библиотека для .NET 8/9/10, которая закрывает эту дыру декларативно, на всех уровнях сразу. Три пакета:
# ядро
dotnet add package Moongazing.Veil             
# HTTP middleware
dotnet add package Moongazing.Veil.AspNetCore  
# structured logs
dotnet add package Moongazing.Veil.Serilog     
Слой 1. Строки и объекты Авто-обнаружение типа данных: email, телефон, карта, IBAN, JWT, IP, API-ключ и маскировка без конфига:
Veil.Mask("john.doe@gmail.com");   
 // j******e@g****.com
Veil.Mask("5425123456789012");      
// 5425 **** **** 9012
Veil.Mask("Bearer eyJhbGci...");    
// Bearer eyJh***...
Для DTO атрибут [Veiled]:
public class CustomerDto
{
    public string Name { get; set; }

    [Veiled]
    public string Email { get; set; }

    [Veiled(Show = 4, Position = VeilPosition.Last)]
    public string CardNumber { get; set; }
}

var masked = Veil.MaskObject(original); // original не трогается
Слой 2. HTTP-трафик:
app.UseVeilRedaction(); // middleware в pipeline

// конфиг:
http.RedactHeaders("Authorization", "X-Api-Key");
http.RedactBodyFields("$.password", "$.creditCard");
http.RedactQueryParams("token", "api_key");
Данные редактируются до того, как попадают в логи. Слой 3. Serilog без изменений в коде:
Log.Logger = new LoggerConfiguration()
    .Destructure.WithVeil()
    .Enrich.WithVeilRedaction()
    .WriteTo.Console()
    .CreateLogger();
Все существующие Log.Information("User {@User}", user) начинают маскировать данные автоматически. Ни один вызов переписывать не нужно. ➡️ NuGet 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #async_news

👨‍💻 Маскировка данных в .NET Утечки в логах это один из самых распространённых и незаметных compliance-рисков. Пароль в трейсе, email в structured log, номер карты в HTTP-дампе. Всё это копится в Kibana и ждёт своего часа. Moongazing.Veil — библиотека для .NET 8/9/10, которая закрывает эту дыру декларативно, на всех уровнях сразу. Три пакета:
dotnet add package Moongazing.Veil             # ядро
dotnet add package Moongazing.Veil.AspNetCore  # HTTP middleware
dotnet add package Moongazing.Veil.Serilog     # structured logs
Слой 1. Строки и объекты ➡️ 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #async_news

📎 Гибридный кэш для .NET с защитой от типичных проблем Кэширование в .NET часто выглядит так: либо IMemoryCache для одного у
📎 Гибридный кэш для .NET с защитой от типичных проблем Кэширование в .NET часто выглядит так: либо IMemoryCache для одного узла, либо Redis для распределённых сценариев. А если нужно и то, и другое одновременно, с нормальной устойчивостью к сбоям, то приходится писать обёртки самим. FusionCache это гибридный кэш для .NET с открытым исходным кодом. Он работает как двухуровневый кэш: L1 в памяти и L2 в распределённом хранилище. Переключение между режимами прозрачно, поэтому код менять не нужно. Минимальный пример без DI:
var cache = new FusionCache(new FusionCacheOptions());

var product = cache.GetOrSet<Product>(
    $"product:{id}",
    _ => GetProductFromDb(id),
    TimeSpan.FromSeconds(30)
);
С DI и настройками устойчивости:
services.AddFusionCache()
    .WithDefaultEntryOptions(new FusionCacheEntryOptions()
        .SetDuration(TimeSpan.FromMinutes(2))
        .SetPriority(CacheItemPriority.High)
        .SetFailSafe(true, TimeSpan.FromHours(2))
        .SetFactoryTimeouts(
            TimeSpan.FromMilliseconds(100),  // soft timeout
            TimeSpan.FromSeconds(2)           // hard timeout
        )
    );
Fail-safe здесь означает: если фабрика данных упала или превысила таймаут, кэш вернёт устаревшее значение вместо ошибки на срок до двух часов. Три сценария, с которыми сталкиваются почти все 1. Cache Stampede. Когда ключ протухает, сотни одновременных запросов идут прямо в базу. FusionCache блокирует параллельные вычисления и делает один запрос вместо ста. 2. Медленная фабрика данных. Если база или внешний сервис тормозит, запросы накапливаются. FusionCache поддерживает soft и hard таймауты: при soft таймауте возвращается устаревшее значение (если оно есть), при hard таймауте бросается исключение, и вы сами решаете, что делать. 3. Согласованность в кластере. Если у вас несколько нод, их L1-кэши могут разойтись. Backplane, например, через Redis Pub/Sub, уведомляет все ноды об изменениях. FusionCache также совместим с HybridCache от Microsoft и может использоваться как его реализация. ➡️ Репозиторий 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view

👨‍💻 Первый дайджест апреля Пошутили и хватит. — Разработчик написал программу для проигрывателя винила — OpenFeature для .N
👨‍💻 Первый дайджест апреля Пошутили и хватит. — Разработчик написал программу для проигрывателя винила OpenFeature для .NETdotnet-adr для архитектурных заметокC# 15 Union Types 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #async_news

🗂 Гайд: где ещё искать работу в IT Cобрали 30 джоб-сайтов на любой вкус: для джунов с первым pet-проектом, для мидлов в поис
🗂 Гайд: где ещё искать работу в IT Cобрали 30 джоб-сайтов на любой вкус: для джунов с первым pet-проектом, для мидлов в поиске удалёнки, для тех, кто хочет работать в геймдеве или уехать в Европу. Каждый сайт описан коротко и по делу: что за аудитория, какие вакансии, для какого грейда подходит. Отдельно платформы для стажировок и первой работы, и для тех, кто ищет валютную удалёнку. ➡️ Искать работу 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта

👨‍💻 Данные важнее алгоритмов Большинство разработчиков переоценивают алгоритмы. Принято считать, что сложная логика и умные
👨‍💻 Данные важнее алгоритмов Большинство разработчиков переоценивают алгоритмы. Принято считать, что сложная логика и умные решения делают код хорошим. Но на практике всё решается на этапе выбора структуры данных. Почему структура данных первична Когда данные организованы правильно, алгоритм становится очевидным. Его не нужно изобретать, ведь он вытекает из формы данных сам. Роб Пайк сформулировал это ещё в 1989 году, и с тех пор ничего не изменилось. Если ясно, кто владеет данными, как они перемещаются по системе и как структура соответствует паттернам доступа, сложные части кода упрощаются без дополнительных усилий. Что происходит, когда структура выбрана плохо Состояние расползается по десяткам мест. Объекты мутируют там, где не должны. Каждое изменение ломает что-то в трёх других местах. Команда тратит время не на новые фичи, а на поиск причин, почему старые перестали работать. Умный алгоритм, написанный поверх плохо организованных данных, не решает проблему. Он только откладывает её. Что меняется после переосмысления структуры Когда команда задаёт правильный вопрос: не "как это починить?", а "как данные должны течь через систему?", запутанный код превращается в понятный пайплайн. Становится короче. Баги исчезают. Новые фичи добавляются без страха сломать существующее. Никакой магии. Просто правильно выбранная структура снимает нагрузку с алгоритма. Практический ориентир Перед тем как писать функцию, полезно ответить на четыре вопроса. Кто владеет этими данными. Где находится источник правды. Как данные попадают из точки А в точку Б. Соответствует ли структура тому, как к ней будут обращаться. Если ответы нечёткие, сложность будет нарастать независимо от качества кода. 💬 Что думаете? Прав ли Роб Пайк или всё уже поменялось? 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #entry_point

📎 Union-типы в действии Мы уже рассмотрели что такое union-тип, теперь пора подумать где это использовать. Бывает, что API принимает как одиночное значение, так и коллекцию. Union с телом позволяет добавить вспомогательный метод прямо в объявление:
public union OneOrMore<T>(T, IEnumerable<T>)
{
    public IEnumerable<T> AsEnumerable() => Value switch
    {
        T single => [single],
        IEnumerable<T> multiple => multiple,
        null => []
    };
}
Использование:
OneOrMore<string> tags = "dotnet";
OneOrMore<string> moreTags = new[] { "csharp", "unions", "preview" };

foreach (var tag in tags.AsEnumerable())
    Console.Write($"[{tag}] ");
// [dotnet]
Поддержка UnionAttribute и IUnion в рантайме ещё не добавлена, поэтому в Preview 2 нужно вручную добавить в проект небольшой полифил:
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct,
        AllowMultiple = false)]
    public sealed class UnionAttribute : Attribute;

    public interface IUnion
    {
        object? Value { get; }
    }
}
После этого синтаксис union работает в полном объёме. ➡️ Блог разработчиков 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #il_люминатор

✏️ Перегрузка и переопределение На технических интервью по C# для джунов и иногда для мидлов вопрос про перегрузки и переопре
✏️ Перегрузка и переопределение На технических интервью по C# для джунов и иногда для мидлов вопрос про перегрузки и переопределения задаётся одним из первых. Оба механизма связаны с методами и их именами. Оба выглядят похоже на первый взгляд. Но работают они в совершенно разных ситуациях и решают разные задачи. Разница между ними принципиальная. Один работает на уровне компиляции, другой — на уровне выполнения программы. Один не требует наследования, другой без него невозможен. ➡️ Как ответить на собесе 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #dotnet_challenge

👀 C# 15 Union Types: наконец-то закрытые типы в языке В C# 15 появился ключевой синтаксис union. Он решает давнюю проблему:
👀 C# 15 Union Types: наконец-то закрытые типы в языке В C# 15 появился ключевой синтаксис union. Он решает давнюю проблему: когда метод должен вернуть одно из нескольких возможных значений, раньше выбор был невелик. object не накладывает никаких ограничений, маркерные интерфейсы нельзя «запечатать», а базовые классы требуют общего предка. Union types убирают все эти ограничения. Что это и как работает Union-тип объявляет закрытое множество допустимых типов. Компилятор знает полный список, поэтому проверяет исчерпываемость switch-выражений прямо при сборке. Простейший пример:
public record class Cat(string Name);
public record class Dog(string Name);
public record class Bird(string Name);

public union Pet(Cat, Dog, Bird);
Переменная Pet хранит ровно один из трёх типов. Присваивание работает через неявное преобразование:
Pet pet = new Dog("Rex");
Console.WriteLine(pet.Value); // Dog { Name = Rex }
switch по такой переменной не требует ветки default или _. Если вы позже добавите четвёртый тип в объявление union, компилятор выдаст предупреждение в каждом месте, где не хватает обработчика.
string name = pet switch
{
    Dog d => d.Name,
    Cat c => c.Name,
    Bird b => b.Name,
};
Фича доступна начиная с .NET 11 Preview 2. ➡️ Блог разработчиков 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #il_люминатор

👨‍💻 Баги, которые уничтожат ваших пользователей Большинство проблем с многопоточностью выглядят одинаково везде. Но часть из них появляется только в конкретной среде. WinForms, WPF и ASP.NET Core имеют свои контексты синхронизации, и если их игнорировать, получаем краш или дедлок там, где вроде бы всё выглядело нормально. Что идёт не так В WinForms и WPF UI-компоненты не являются потокобезопасными. Обновлять их можно только из UI-потока. Если фоновый поток попытается напрямую записать что-то в label.Text или textBox.Value, получаем InvalidOperationException. В WPF для этого используется Dispatcher.BeginInvoke, в WinForms — Control.Invoke или Control.BeginInvoke. Казалось бы, очевидное правило. Но баг всё равно появляется: чаще всего тогда, когда разработчик делает Task.Run, внутри него обращается к UI, а анализатор это не видит. С Dispatcher.Invoke другая история. Это синхронный вызов, он блокирует текущий поток до завершения. Если вызвать Invoke из самого UI-потока или из кода, который UI-поток уже ждёт, получаем дедлок. Правило простое: почти всегда нужен BeginInvoke (асинхронный), а не Invoke. Как находить такие баги до прода Статические анализаторы: Roslyn, AsyncFixer, Microsoft.VisualStudio.Threading.Analyzers и ThreadSafetyAnalyzer умеют находить прямые обращения к UI из неправильного потока, синхронные блокировки async-методов и потенциальные дедлоки в диспетчере. Подключить их можно через NuGet:
dotnet add package Microsoft.VisualStudio.Threading.Analyzers
dotnet add package AsyncFixer
После подключения анализаторы начинают предупреждать прямо в IDE, до сборки. Часть правил даже предлагает автофикс. На практике это работает: после включения анализаторов в одном проекте удалось найти три гонки данных ещё до того, как они добрались до пользователей. 📍 Навигация: ВакансииЗадачиСобесы 🐸 Библиотека шарписта #sharp_view