Внимание! Эта статья не является «серьезной аналитикой». Только мои мысли и наблюдения.

Любите наблюдать за развитием дотнета? Вот, и я люблю. В данный момент не существует опубликованного списка изменений для будущих .NET 11 и C# 15, не говоря уж о более поздних версиях. Даже Devblogs пока хранит молчание. Благо, что C# - быстро развивающийся язык, и кое-что мы можем понять даже сейчас, если посмотрим, над чем активно ведется работа, а так же по запрашиваемым сообществом фичам.

Runtime async

Наверное, вы уже слышали о runtime async, даже есть отличная статья на Хабре. Если коротко, это позволит создавать легковесные асинхронные задачи, как горутины в Go, управление которыми ляжет на рантайм, без нагрузки на потоки ОС. Без преувеличения, самая ожидаемая фича, которая позволит C# выбить главный козырь из рукава Go.

UPD. @Lewigh верно подметил, что в статье говорится о несколько ином подходе:

Для реализации Async2 были рассмотрены два подхода: размотка стека (tasklets, stack unwindind) и JIT-сгенерированные машины состояний (continuations, JIT State Machine). Подход на основе JIT оказался предпочтительным благодаря лучшей совместимости с текущей инфраструктурой .NET, меньшим накладным расходам и более высокой производительности в большинстве сценариев. Размотка стека, хотя и поддерживает сложные конструкции, такие как byref и span, оказалась менее практичной из-за увеличения времени пауз сборки мусора и сложности реализации.

Самое главное, что всем знакомый синтаксис async\await не поменяется, так что это настоящий must have.

Можете сами ознакомиться с Issue по теме.

Union types

Типы объединений в функциональном стиле стали бы интересной возможностью в C#. Информация о них появилась еще в августе этого года, когда Мадс Торгерсен, ведущий разработчик языка C#, поделился планами об этом в видео.

Мотивация понятна: вы можете описывать типы, которые более дословно соответствуют API (как в TypeScript), например типичное:

{
  ...
  someValue : string | int
}

Теперь можно будет описать новой конструкцией:

public union Union<T1, T2>(T1, T2);
...
Union<string, int> SomeValue;

Обратите внимание, что синтаксис объединений еще может поменяться.

Обсуждение по теме.

Runtime reflection?

Звучит громко, понимаю. В данный момент рефлексия - самое слабое место C#. При активном развитии AOT и source generators, именно рефлексия вставляет палки в колеса. К счастью, развитие языка показывает, что и это временные трудности. Из недавнего можно вспомнить LibraryImport, UnsafeAccessor, partial events\constructors\properties. А что будет дальше?

Вероятно, нас ждут возможности по типу Enum.Source.Generator, но из коробки. К сожалению, единого мнения пока нет.

Tail return

В C# любая рекурсия (т.е. вызов функцией самой себя) требует O(n) памяти только для стека вызовов, то есть ваш алгоритм не может занимать меньше O(n) памяти. Как быть? Интересное предложение о добавлении нового ключевого слова для описания хвостовой рекурсии появилось аж в 2019 году.

void M(int x)
{
    ...
    tail return M(x - 1);
}

Хвостовая рекурсия - это особый вид рекурсии, при котором последний шаг в функции - это вызов самой себя.

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

Преимущества хвостовой рекурсии:

  1. Меньше памяти - такие программы используют меньше места в памяти.

  2. Нет переполнения - это особенно важно, если в программе много рекурсивных вызовов.

Функциональные (и не только) языки активно используют эту фичу, уменьшая накладные расходы на вызов. Надеюсь, C# рано или поздно реализует данную возможность из коробки.

К сожалению, последнее обновление в обсуждении числится началом января этого года.

Комментарии (19)


  1. Gromilo
    29.12.2025 08:33

    Runtime async

    Чёт страшно мне. На бэкендах привык разделять асинхронный и синхронный код, как код с IO и код без IO. Код без IO является ещё и чистыми функциями по возможности. Позволяет делить методы на части вида: грузим, что-то делаем, сохраняем.

    Просто помню время, когда данные грузились в недрах каких-то функцих и этого нельзя понять, пока не просмотришь ВСЁ.


  1. Lewigh
    29.12.2025 08:33

    Runtime async

    Наверное, вы уже слышали о runtime async, даже есть отличная статья на Хабре. Если коротко, это позволит создавать легковесные асинхронные задачи, как горутины в Go, управление которыми ляжет на рантайм, без нагрузки на потоки ОС.

    Боюсь Вы не до конца поняли как статью так и механику.

    В указанной Вами статье:

    Для реализации Async2 были рассмотрены два подхода: размотка стека (tasklets, stack unwindind) и JIT-сгенерированные машины состояний (continuations, JIT State Machine). Подход на основе JIT оказался предпочтительным благодаря лучшей совместимости с текущей инфраструктурой .NET, меньшим накладным расходам и более высокой производительности в большинстве сценариев. Размотка стека, хотя и поддерживает сложные конструкции, такие как byref и span, оказалась менее практичной из-за увеличения времени пауз сборки мусора и сложности реализации.

    указано что как раз был выбран путь не как в Go. Если сильно упростить - останеться та жа стейт-машина но создаваться и поддерживаться она будет на уровне рантайма.

    Без преувеличения, самая ожидаемая фича, которая позволит C# выбить главный козырь из рукава Go.

    Ничего никто выбивать не пытаеться, у .Net итак все очень хорошо и никаких козырей у Go нет. В .Net, JVM и Go у каждого свой подход к решению проблемы, со своими плюсами и минусами.

    К примеру для виртуальных потоков Java главная задача была - это безболезненно мигрировать огромное количество проектов. Для Go - создать шайтан машину которое позволит разработчикам вообще не грузить голову по поводу управления задачами в среднем по больнице. Для C# - это - наглядность и управляемость.


    1. Ydav359 Автор
      29.12.2025 08:33

      Спасибо за замечание, учту!


  1. iamkisly
    29.12.2025 08:33

    С нетерпением жду статью "Как поменяется .NET и C# в ближайшие годы В РОССИИ ?" потому что пока что весь локальный рынок захватили java и go стеки, и шарп остался какой-то нишевой штукой на грани легаси, где только Dodo и Ozon мейнстримно поддерживают его


    1. Zufir
      29.12.2025 08:33

      Я работаю в банке. Крупном. У нас тут много C#. Сейчас вот с 8 на 10 переходим потихоньку. Так что не все так печально.


      1. kol92v
        29.12.2025 08:33

        Я тоже работаю в банке, и у нас наоборот отношение к шарпам как к Легаси и поэтому его переписывают на Java/Kotlin :(


    1. Spearton
      29.12.2025 08:33

      В рф в принципе не так уж и много вакансий с НЕ легаси, в сравнении с другими рынками, а всякие сберы и яндексы несут мусорные технологии (например у яндекса это приложения на электроне или другом подобном фреймворке, вместо нормальных кроссплатформенных приложений)


  1. Mikle2024
    29.12.2025 08:33

    Я полный профан в разработке, хоть мне и легко давались практика и теория C# несколько лет назад. Все Испортил ИИ, какой самый сладкий чит для новичков. Но в одном я уверен точно, никогда в точных дисциплинах не побеждала гуманитарная лабузня, как долго не хвалили питон за его простоту и кучу фичей, это та же лобузня, которая со временем погаснет, а группа С будет развиваться дальше. Разве что позаимствует какие то мелкие элементы из ушедшего в древность питона, или GO. На мой взгляд такие языки, как заплатки на штаны, которые нужно срочно подлатать, пройдет время и все придут к мнению что они устарели. Таких заплаток будет еще оченьмного. А группа С языков, это как манекен, который постепенно из квадратного безформенного скелета превращается в полноценный живой образ на протяжении десятков лет. Именно точность процессов под капотом дают тот самый непревзрйденный звук двигателя у известного бренда. А эти заплатки звучат как копии китайских авто, все красиво и дорого но чувствуется где-то подвох.


    1. miklin-ag
      29.12.2025 08:33

      Разные языки используются для разных же целей. А ваша "группа C языков", это кажется вообще что-то из эзотерики - не понятно, почему вы в одну кучу сложили C и C#


  1. Nagg
    29.12.2025 08:33

    В C# любая рекурсия (т.е. вызов функцией самой себя) требует O(n) памяти только для стека

    Это не так, JIT компилятор где сможет, прекрасно расставляет тейл коллы сам (а в очень редких ситуациях может даже развернуть в цикл). tail. prefix который использует F# это больше как обязательное требование к рантайму, в духе "мне все равно как, сделай тут tail call, в случае если быстрый (имплицитный) тейл-колл нельзя вставить, джиту придется вставлять специальный хелпер колл от чего будет удар по перфу.

    Я не думаю что есть хоть какие шансы на появление этого в синтаксисе C#, хз зачем вы его тут перечислили.


    1. navferty
      29.12.2025 08:33

      Вот тоже, помню ещё лет 5 назад экспериментировал с рекурсией. Если компилировать метод с рекурсивным вызовом в последней инструкции в Release конфигурации, то реально он компилируется как цикл.

      В этом можно убедиться, если намеренно сделать рекурсию бесконечной. Переполнения стека не происходит, и программа крутится бесконечно (в отличие от Debug mode, где stack overflow exception происходит практически сразу после запуска).


    1. equmag
      29.12.2025 08:33

      JiT действительно может, но Roslyn просто не эмитит ему эти инструкции, потому что это меняет семантику, а оптимизации по определению не должны менять результат исполнения программы.

      Мне было бы очень интересно посмотреть на примеры, которые стабильно эмитят tail call потестить


      1. Nagg
        29.12.2025 08:33

        Какую именно это меняет семантику и результат программы? наличие или нет StackOverflowException? это не семантика


      1. Nagg
        29.12.2025 08:33

        Мне было бы очень интересно посмотреть на примеры, которые стабильно эмитят tail call потестить

        вот вам 2 примера https://godbolt.org/z/9ne5K5G16


  1. equmag
    29.12.2025 08:33

    Должен отметить, предложение о хвостовой рекурсии есть в IL (поскольку есть в F#), но было отклонено на уровне LDM. Причина: ломает стек трейс, сильно травмирует отладку, есть комментарий Мэдса на тему.

    Из планов на .NET11 известны ещё closed модификатор, nullable async/foreach, развивается unsafe блок в статический анализатор как было с nullable reference types, top-level methods и ещё всякого разного по мелочи.

    Так-то да, из крупных анонсов ждем Union types и Runtime async (+extension everything), но об этом уже давно известно, ещё со времён .Net9. Самое интересное как по мне происходит в нишевых гитхаб коммитах


    1. Nagg
      29.12.2025 08:33

      развивается unsafe блок в статический анализатор как было с nullable reference types

      Там скорее про то что большое кол-во public API начнут требовать unsafe{} контекст, т.к. они не безопасны. Остальное вокруг этого.


    1. voroninp
      29.12.2025 08:33

      Они разве не забили на extension everything?


    1. Ydav359 Автор
      29.12.2025 08:33

      Спасибо!


  1. gen_dalf
    29.12.2025 08:33

    Скоро нужно будет уточнять каким подмножеством C# ты владеешь. Стили и наборы используемых фич будут ощущаться как отдельные языки программирования.