Как поменяется .NET и C# в ближайшие годы?

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

Любите наблюдать за развитием дотнета? Вот, и я люблю. В данный момент не существует опубликованного списка изменений для будущих .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# рано или поздно реализует данную возможность из коробки.

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

@Ydav359
29.12.2025 13:17 UTC
Первоисточник

Комментарии

@Gromilo
29.12.2025 08:33 UTC
0

Runtime async

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

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

@Lewigh
29.12.2025 08:50 UTC
+12

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# - это - наглядность и управляемость.

@Ydav359
29.12.2025 09:18 UTC
0

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

@iamkisly
29.12.2025 09:24 UTC
+4

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

@Zufir
29.12.2025 10:02 UTC
+4

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

31.12.2025 02:59 UTC
+1

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

24.01.2026 14:46 UTC
+2

Сравнивал java и c# на уровне экосистемы и IDE. У Java убогая IDE.

@
29.12.2025 22:34 UTC
0
НЛО прилетело и опубликовало эту надпись здесь
@Mikle2024
29.12.2025 10:14 UTC
+3

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

@miklin-ag
29.12.2025 23:23 UTC
0

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

@Nagg
29.12.2025 14:52 UTC
+1

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

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

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

@navferty
29.12.2025 19:28 UTC
+1

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

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

@equmag
30.12.2025 14:29 UTC
0

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

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

30.12.2025 16:08 UTC
0

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

30.12.2025 16:10 UTC
0

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

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

@equmag
30.12.2025 14:13 UTC
+1

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

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

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

@Nagg
30.12.2025 16:12 UTC
0

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

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

@voroninp
30.12.2025 17:07 UTC
0

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

@Ydav359
31.12.2025 04:11 UTC
0

Спасибо!

@gen_dalf
30.12.2025 20:13 UTC
+2

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

@donRumatta
02.01.2026 20:43 UTC
0

По Union types, подскажите, плиз, в 2 словах, чтоб понять, отчего с ними все так носятся)

  1. чисто семантически - это что за поле такое, что и int и string принимает

  2. неужели в строгом C# - это мастхэв?

  3. как потом использовать, если, например, хочешь на 2 умножить: 2 * 2 = 4, "абв" * 2 = "абвабв" - попахивает скриптом, но не type)

  4. в чем проблема объявить 2 поля, особенно сейчас, когда cursor за тебя весь бойлерплейт фигачит)

@amironov
03.01.2026 07:24 UTC
+1

Есть реализации union types на соурс генераторах https://github.com/kolebynov/Dusharp, https://github.com/domn1995/dunet. Посмотри примеры использования, там ответы на все твои вопросы.