В следующем месяце выходит очередная версия нашего любимого языка программирования. Чем не повод присесть на кухне с рюмкой чая и обсудить, что не так с современными версиями C#?


В студенческие годы была у меня книга небезызвестного датчанина о небезызвестном языке программирования. И хотя я испытывал неподдельные тёплые чувства к C++, книгу ту я не осилил даже наполовину (настолько унылым было чтиво). Тем не менее, это не помешало мне продолжать верить в предначертанную нам с плюсами судьбу и летом 2011-го пойти устраиваться программистом на этом языке.

Итог собеседования был следующий: C++ я не знаю. Но мне было предложено попробовать себя в C#. Чувства были задеты, но я согласился: хотелось уже начать работать.

Тестовое задание состояло в написании игры “Змейка”. Для усложнения поле представляло собой карту России, передвигаться можно было только в её пределах, а расти предлагалось за счёт поедания крупных городов. Игра должна была запускаться в браузере с использованием ныне покойного Silverlight.

Приложение было написано и одобрено, я был принят на своё первое место работы, а С++ остался в прошлом. Так волею судеб я стал разработчиком на C#, полюбил этот язык, и по сей день неразлучен с ним. К сожалению, иногда у меня возникает чувство, что с ним не всё в порядке.

Оглавление

А есть ли проблема?

Рано или поздно любой программист, увлекающийся C++, приходит к выводу: “Никто не знает этот язык полностью”. Но, хотя наши с плюсами дороги разошлись много лет назад, в последние годы мысль эта стала всплывать у меня снова. Правда, в слегка изменённом виде: вместо ++ я вижу там #. Конечно, шарпу ещё очень далеко до сложности творения Бьёрна Страуструпа. Однако многие новшества начинают вызывать обеспокоенность за былое изящество C#.

Но прежде, чем мы начнём аккуратно раскладывать на лабораторном стекле синтаксические конструкции, отвечу на абсолютно справедливое замечание: “Никто ведь не заставляет пользоваться новыми фичами”. Т.е. проблемы по факту нет, и зачем тогда весь этот разговор? Тут интерес скорее личный.

Я, как разработчик .NET библиотеки, иногда сталкиваюсь с запросами пользователей на расширение API. Бывает, что я и сам вижу в чужом коде почву для новых функций или переработки старых. Но целесообразны ли изменения? Насколько увеличится сложность API? Так ли неудобно решать определённые задачи при нынешнем устройстве библиотеки?

Лаконичность контрактов и простота решения реальных пользовательских проблем — параметры, между которыми постоянно приходится балансировать. И мне очень интересно, как с такой эквилибристикой справляются в Microsoft при разработке инструмента, которым я пользуюсь ежедневно.

Безусловно, любой язык программирования должен развиваться. Да чего уж скрывать, я и сам использую многие новинки. Но так ли без них было сложно и неудобно? И хотя мои претензии могут звучать ультраконсервативно в духе “Раньше байты были восьмибитнее”, хочется поделиться своими мыслями и обсудить их вместе с вами.

Точка отсчёта

Согласно официальной летописи, C# к моменту написания статьи насчитывает 17 ревизий. Любопытно, что первые семь версий (до шестой включительно) охватывают период в 13 лет, тогда как остальные десять были выпущены всего за 8:

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

Бурный рост количества фич в C# начался примерно между седьмой и восьмой версиями. Вот, например, график роста количества ключевых слов (keywords):

Как собраны данные
  1. Исходники страницы C# Keywords официальной документации лежат в файле docs/docs/csharp/language-reference/keywords/index.md. Поэтому взяты изменения этого файла и собраны списки ключевых слов.

  2. Но коммиты есть только до ноября 2016-го. Данные о перечне ключевых слов до этой даты собраны вручную из архивов MSDN.

  3. В какие-то моменты времени одни и те же ключевые слова считались разными в зависимости от контекста (например, partial при объявлении классов и методов). При сборе данных такого разделения не делалось.

Можно также взглянуть на содержимое файла Syntax.xml в репозитории dotnet/roslyn. Он используется для генерации компилятора Roslyn и содержит все синтаксические правила C#. Отсчёт начнём с релиза Visual Studio 2015 RTM, т.е. с июля 2015-го, когда Roslyn стал компилятором по умолчанию в VS (стало быть, начал поддерживать все фичи языка). Вот как с годами менялось количество узлов в указанном файле:

Как собраны данные
  1. Взяты коммиты файла Syntax.xml. Файл два раза в истории перемещался/переименовывался, изменение отслежены вплоть до первой версии исходного документа.

  2. Для каждого коммита собрано количество дочерних узлов элемента Tree.

Помимо того, что Microsoft и сама начала активно развивать язык, компания предоставила всем нам возможность предлагать фичи и голосовать за них в соответствующем репозитории на GitHub. Поэтому многие кинулись создавать запросы, в которых описывали свою профессиональную боль и способы её решения через новые языковые конструкции. Каюсь, за мной тоже числятся такие предложения (раз и два). И я очень рад, что они были отклонены.

Если зайти в папку proposals, то стартовать подпапки будут с шестой версии. Но в соответствующей директории всего три небольших файла. Вероятно, это ещё были внутренние хотелки команды разработчиков языка. А вот в папке с материалами по седьмой версии будут уже документы со ссылками на дискуссии. Здесь мы и приходим к точке отсчёта, когда стали проскакивать сомнительные (с моей абсолютно субъективной и неавторитетной точки зрения) новые функции C#.

Также стоит отметить любопытный момент. Существует стандарт ECMA-334, описывающий полную спецификацию C#. На момент написания статьи последняя опубликованная версия седьмая. И в ней нет, например, ключевого слова and. А слово это появилось аж в C# 9, т.е. четыре версии назад. Более того, в официальном репозитории, где ведётся разработка стандарта, есть две ветки: draft-v8 и draft-v9. И даже в черновике девятой версии в файле с описанием грамматики языка отсутствует тот самый and. То есть, официальная спецификация и даже черновики её новых редакций не поспевают за фактическим развитием C#.

Когда остановиться невозможно

Посмотрим, например, на локальные функции, добавленные в C# 7.0. Выглядят, как обычные методы, разве что без модификаторов доступа. Значит, наверное, можно и статическими их делать? С восьмой версии можно — говорит Microsoft. А ещё в сигнатурах методов есть возможность использовать атрибуты, на параметрах или возвращаемом значении. Как там дела с локальными функциями? Вот вам C# 9, пожелание реализовано — отвечает Microsoft.

Но разработчики языка пошли дальше. По их мнению, пространства имён и метод Main так сильно пугают новичков, что те бегут изучать Python (информация непроверенная), а потому в той же девятой версии стало возможным отбросить эти ужасы. Top-level statements позволили писать код так, будто мы находимся внутри Main, существующего где-то там. И это правда, ибо фича не более чем синтаксический сахар. Объявлять методы при таком подходе помогают именно введённые ранее локальные функции.

Кстати, лямбда-функции ведь очень похожи на локальные. Обладают некоторыми неудобствами по сравнению с последними, но всё же. В локальных функциях можно объявлять опциональные параметры и использовать атрибуты, а в лямбда-функциях почему нет? C# версий 10 и 12 исправляет эти упущения.

Или рассмотрим ключевое слово ref, позволяющее передать в метод объект по ссылке. И снова C# 7.0 расширяет горизонты дозволенного. Теперь можно объявлять переменные через ref (создавая псевдоним для другой переменной) и даже возвращать значение по ссылке. Дальше — больше: ref readonly, ref struct, ref-поля, scoped ref.  При этом нужно ещё научить компилятор не ругаться на использование тех же ref-структур в дженериках или попытки реализовать такими структурами интерфейсы.

Обширный пласт функциональности связан с записями (records). Изначально ключевое слово record позволяло быстро объявить класс с набором свойств, причём всякую обвязку вроде Equals и ToString компилятор генерировал сам. А что если хочется сделать такой тип значимым (value type), а не ссылочным? Встречайте — record struct. Связка этих ключевых слов (а заодно и record class в качестве псевдонима для record) появилась в C# 10 и повлекла за собой сопряжение с модификатором readonly, применимым с C# 7.2 к обычным структурам. В итоге сейчас можно объявлять записи такими способами:

record A();
record class B();
record struct C();
readonly record struct D();

На dev.to, к слову, есть статья, в которой приведён такой код:

public ref readonly record struct Point(double X, double Y);

Думается, что автором является его величество ИИ, ибо скомпилировать такую конструкцию не удастся. Хотя её наличие отлично бы вписалось в тенденцию, показанную выше: readonly ref struct ведь существует.

При этом в записи можно добавлять методы и свойства, переопределять их и т.д. Иными словами, очень похоже на обычные классы и структуры. Вот только последние не поддерживают тот замечательный синтаксис, в котором имя типа сочетается с конструктором. Здесь история C# приводит нас к концепции первичных конструкторов (primary constructors), появившихся в 12-ой версии языка. К слову, данная фича находится в лидерах по количеству отрицательных реакций — 186 голосов “за” и 96 “против”.

Как подсчитаны голоса
  1. Взяты документы с предложениями новых фич из папки proposals в репозитории dotnet/csharplang (файлы в подпапках csharp-<version>).

  2. Внутри файлов найдены ссылки на champion issues, в рамках которых велись обсуждения нововведений.

  3. В каждом предложении-чемпионе подсчитаны реакции пользователей (+1, heart и hooray — голоса “за”, -1 — голоса “против”). Разумеется, когда один человек поставил, например, и +1 и heart, прибавится только один голос “за”.

  4. На основе реакций для каждого issue вычислены два параметра: like ratio (отношение числа положительных голосов к общему числу голосов) и dislike ratio (отношение числа отрицательных голосов к общему числу голосов). Отсортировав предложения по убыванию значения каждого параметра получены два списка.

  5. Также параллельно созданы два набора, где предложения упорядочены по убыванию абсолютного числа голосов “за” и “против” соответственно.

  6. Сопоставив соответствующие списки друг с другом получены фичи-лидеры и фичи-аутсайдеры.

  7. Метод не суперточный, но такового я и не придумал. Тем более, неизвестно, какие ещё эмодзи могут использоваться людьми и какой смысл они в них вкладывают. Но это мелочи, не сильно меняющие позиции в рейтингах.

Тем не менее, всё это примеры полезных нововведений. Локальные функции и записи я и сам время от времени использую. Разве что top-level statements полюбить не смог, и, кажется, я не один такой, учитывая, что Microsoft даже добавила галочку Do not use top-level statements при создании нового проекта в Visual Studio.

Когда нужно больше ключевых слов

Интересная история приключилась с native sized integers. Введённые в C# 9 ключевые слова nint и nuint представляли собой “улучшенные” версии IntPtr и UIntPtr соответственно. Улучшение заключалось в поддержке арифметики, и неявных приведениях между числовыми типами. Иными словами, вот такой код не скомпилировался бы:

IntPtr a = 2;
IntPtr b = 3;
var c = a + b;

И такой тоже:

IntPtr a = (IntPtr)2;
IntPtr b = (IntPtr)3;
var c = a + b;

А с nint пожалуйста:

nint a = 2;
nint b = 3;
var c = a + b;

Но в C# 11 в Microsoft решили добавить все эти возможности и в давно живущие среди нас IntPtr и UIntPtr. А если нет разницы, то пусть nint и nuint будут в конце концов просто псевдонимами для старых типов. И вот мы имеем два ключевых слова, которые не добавляют никакой пользы.

Забавный факт: выглядят они как обычные псевдонимы простых типов (вроде int или byte), но объявить переменную с именем int вы не сможете, а с nint запросто:

nint nint = 4;

Так получилось потому, что nint и nuint это контекстные ключевые слова. Кроме того, если не знать и�� историю, можно подумать, а чего именно IntPtr и UIntPtr удостоились чести иметь псевдонимы? Почему, например, не TimeSpan? Думается, в жизни большинства разработчиков он встречается даже чаще.

Есть ещё один пример внезапного пополнения списка ключевых слов. И даже не двумя, а сразу тремя. Речь про сопоставление с образцом (pattern matching, aka сопоставление шаблонов). Фича безусловно полезная, значительно упрощающая жизнь. Будучи добавленным в C# 7.0, паттерн матчинг пережил множество расширений и сейчас представляет собой очень мощный инструмент.

Эволюция сего функционала привела к появлению в C# 9 логических паттернов (logical patterns), а вместе с ними и новых ключевых слов: not, and и or (на всякий случай, оставлю ссылку на сообщение, в котором рассказывается, почему нельзя обойтись привычными !, && и ||). Кроме того, сопоставление с образцом доступно не только в конструкциях switch, но и в if посредством использования оператора is.

И хотя логика добавления новых операторов понятна, есть ощущение, что они лишние. При этом вариант лучше придумать не могу. Критикую и не предлагаю.

Когда догадаться сложно

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

Начало было положено задолго до обозначенной нами точки отсчёта. Думаю, мало кто из программистов, кому довелось впервые увидеть модификатор доступа protected internal, догадывались, что союз между этими двумя словами вовсе не “и”, а “или”. Кажется вполне разумным читать это как “можно обращаться только из производного класса в рамках текущей сборки (assembly)”. Но реальность жестока. Правильная интерпретация: “можно обращаться из текущей сборки (из любого класса) или из производного класса (из любой сборки)”.

Когнитивный диссонанс и потребность в модификаторе доступа, соответствующем логичной мысли выше, привели к появлению не менее странного private protected в C# 7.2. Кто знает, возможно, в будущем мы увидим появление, например, private protected internal (пусть интерпретация будет такая: “можно обращаться только из производного класса в рамках текущего пространства имён”).

Ещё одним интересным объектом для рассмотрения является default. Давным-давно введённый оператор позволяет получать значение по умолчанию для любого типа. Особенно удобно это для, например, дженериков:

public T Foo<T>()
{
    // …
    return default(T);
}

C# 7.1 упрощает оператор до литерала:

public T Foo<T>()
{
    // …
    return default;
}

При этом издревле конструктор без параметров назывался конструктором по умолчанию (default constructor). И там и там слово default, выходит, и default и new T() должны давать нечто одинаковое. Или нет?

Объявим структуру, представляющую число, которое не может быть меньше 10 (такие у нас специфические желания):

private struct A
{
    private int _x = 10;

    public A(int x)
    {
        if (x < 10)
            throw new ArgumentException("X is too small.", nameof(x));

        _x = x;
    }

    public override string ToString() => _x.ToString();
}

Далее создадим дефолтный экземпляр этого типа разными способами:

A a1 = default(A);
Console.WriteLine($"A1 = {a1}");

A a2 = default;
Console.WriteLine($"A2 = {a2}");

A a3 = new();
Console.WriteLine($"A3 = {a3}");

A a4 = Activator.CreateInstance<A>();
Console.WriteLine($"A4 = {a4}");

В консоли будут напечатаны такие строки:

A1 = 0
A2 = 0
A3 = 0
A4 = 0

Здесь перед нами предстаёт интересная особенность оператора и литерала default: он игнорирует инициализацию полей (на что мне обратили внимание в комментариях к другой моей статье). И хотя, как и в примере с protected internal, мы можем (и должны) обратиться к документации, с первого взгляда поведение кажется неочевидным.

Начиная с C# 10 можно добавить в структуру конструктор без параметров, и вывод консоли поменяется:

A1 = 0
A2 = 0
A3 = 10
A4 = 10

Такое поведение вызвало споры, а фича попала на верхние строчки анти-рейтинга нововведений — 40 положительных голосов и 29 отрицательных.

Выходит, что слово default не совсем применимо одновременно и к соответствующему оператору/литералу, и к new T(). В Microsoft тоже это поняли, так что в статье Use constructors начиная с 20 апреля 2019 компания не использует термин конструктор по умолчанию — теперь это конструктор без параметров (parameterless constructor). Последняя версия текста, где фигурирует словосочетание default constructor, датируется 28 февраля 2019.

Заключение

Конечно, есть ещё, на что побрюзжать. Например, на возможность реализовывать методы прямо в интерфейсе (default interface methods), появившуюся в C# 8 и вызвавшая возмущение — 89 дизлайков против 142 голосов “за”. Но, перефразируя Маяковского: если фичи добавляют — значит — это кому-нибудь нужно? Без сомнений.

Язык расширяется, а разработчики получают возможность решать свои задачи чуточку (а иногда и ого-го как) быстрее и проще. Но всё-таки иногда возникает ощущение утраченной стройности, чего-то, что делало язык одновременно простым и мощным.

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


  1. Arragh
    24.10.2025 15:01

    Меня уже давно напрягает перегруженность C# всякими фичами, некоторые из которых выглядят весьма сомнительно. Взять те же “field” в геттерах/сеттерах - зачем они это сделали? Я не смог придумать ни одного сценария, где бы мне понадобилось к ним прибегнуть. И таких примеров вагон и маленькая тележка.

    Лучше бы вносили побольше удобства в функциональность языка. Я помню, как я радовался, когда наконец-то добавил возможность использовать лямбда-выражения внутри лямбда-выражений при обращении к БД - вот это было просто супер. По-моему это фишка появилась в .NET 5 или 6, точно не помню.

    А в .NET7 наконец-то добавили метод PatchAsJsonAsync, который избавлял от головной боли с конвертацией модели, что тоже очень обрадовало.

    Вот такого бы функционала побольше добавляли, а не чепуху всякую.


    1. Gromilo
      24.10.2025 15:01

      Взять те же “field” в геттерах/сеттерах - зачем они это сделали?

      А мне нравится. Просто как хочешь логику написать в {get; set;} приходится поле заводить. А так нам просто дали доступ до автогенерённого. Выглядит как шлифовка синтаксиса, а не как новая фича.


      1. Spearton
        24.10.2025 15:01

        Field не в пример вообще как-будто))


    1. holgw
      24.10.2025 15:01

      Лучше бы вносили побольше удобства в функциональность языка.

      возможность использовать лямбда-выражения внутри лямбда-выражений при обращении к БД

      добавили метод PatchAsJsonAsync

      А какое отношение эти две фичи имеют к функциональности языка?

      Первое -- это про EF, а не про сам язык, второе -- вообще просто добавление экстеншен-метода в библиотеке System.Net.Http.Json.


    1. Ydav359
      24.10.2025 15:01

      field прекрасно упрощает написания свойств в WPF\Avalonia и защищает от возможной ошибки при копипасте полей для реактивных свойств.


    1. posledam
      24.10.2025 15:01

      А в .NET7 наконец-то добавили метод PatchAsJsonAsync

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

      использовать лямбда-выражения внутри лямбда-выражений при обращении к БД

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

      Но это ладно. Уж простите за резкость. Ну правда. Что за постоянное нытьё про "перегруженность". Оно чем-то мешает? Никто не заставляет пользоваться всеми фичами языка. Более того, мне трудно представить человека, который вообще все фичи разом использует, уверен, что большинство разработчиков не знают или не помнят и половины — это им совершенно не мешает жить. Вот совсем. Никаких проблем с этим нет.

      Чем мешает "перегруженность"? Или кто-то принимает экзамен на знание всех фич и ключевых слов? :)


      1. Arragh
        24.10.2025 15:01

        Да, это не фичи языка, согласен, не так выразил мысль. Но суть, надеюсь, понятна. Можно и самому написать нужные методы, но лучше, когда они есть из коробки, так как именно это и добавляет удобства. Мы же не пишем сортировку руками, а применяем OrderBy. Ведь именно благодаря таким удобствам я могу сконцентрироваться на логике приложения, а не набирать тонны бойлерплейт-кода.


        1. vvdev
          24.10.2025 15:01

          Мы же не пишем сортировку руками, а применяем OrderBy

          Вообще-то, "мы" ещё как пишем, потому, что OrderBy - это куча аллокаций, да ещё и приведение к IEnumerable<> со всеми вытекающими.

          "Мы" и поиск, случается, пишем, и вообще много всего, что есть в стандартной библиотеке.

          Так что "мы" разные.


        1. posledam
          24.10.2025 15:01

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


        1. W_o_o_f
          24.10.2025 15:01

          а не набирать тонны бойлерплейт-кода.

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


      1. Femistoklov
        24.10.2025 15:01

        Чем мешает "перегруженность"? Или кто-то принимает экзамен на знание всех фич и ключевых слов? :)

        На собесах спрашивають.


        1. Krey
          24.10.2025 15:01

          И на внутренних переатестациях создатели тестов видимо считают свою работу не выполненной, если не добавят все нововведения в варианты ответов


        1. posledam
          24.10.2025 15:01

          Я такое не спрашиваю :)


      1. lgorSL
        24.10.2025 15:01

        Оно чем-то мешает? Никто не заставляет пользоваться всеми фичами языка. Более того, мне трудно представить человека, который вообще все фичи разом использует, уверен, что большинство разработчиков не знают или не помнят и половины — это им совершенно не мешает жить. Вот совсем. Никаких проблем с этим нет.

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

        И если проект на несколько человек (а ещё "лучше" - легаси), то там кто-то мог наиспользовать всяких незнакомых фич и потом с этим придётся жить. Это получится как с С++ - вполне можно написать хороший код на нём "с нуля", но если придётся разбираться в чужом, то иногда без поллитра не разберёшься.

        P.S. Ещё добавлю что есть Scala, где разработчики пошли по пути гибкости языка и возможности писать почти любую языковую конструкцию внутри любой другой - получилось просто и очень мощно. Например, можно объявить функцию внутри функции - это не "специальная фича языка", это просто поддержа вложенности. Можно вообще объявить класс внутри функции внутри объекта внутри класса - и это всё скомпилируется. Отдельного понятия для "статических локальных функций" нет, в нём нет смысла.


        1. Dhwtj
          24.10.2025 15:01

          template<typename T>
          auto operator->*(T&& t) -> decltype(auto) {
              return [&]<typename... Args>(Args&&... args) {
                  return std::invoke(std::forward<T>(t), 
                                    std::forward<Args>(args)...);
              };
          }

          Разберись)))


        1. aftertherainbow
          24.10.2025 15:01

          но если придётся разбираться в чужом, то иногда без поллитра не разберёшься

          Такое можно написать на любом языке любых версий, тут вопрос к разработчику


        1. posledam
          24.10.2025 15:01

          Точно мешает.

          Прошу прощения, но я не вижу помех. Я конечно опираюсь на собственный опыт и опыт моих команд, и в этом опыте часть новых фич активно применяется, а некоторые редко, но характеристика "мешает" не натягивается, даже при всём желании. Может у вас по-другому, я был бы благодарен, если поделитесь кейсами.

          Это всё становится делать сложнее и результат либо дороже, либо хуже.

          Конечно. Но как это мешает? Я не понимаю. В естественных языках каждый день тоже появляются новые слова, новые идиомы и выражения.

          Давайте иначе посмотрим на ситуацию. Много людей, включая лично меня, довольны тем фактом, что язык развивается и в нём появляются новые фичи. Не все фичи радуют, а некоторые приходится ждать годами. Что предлагаете? Заморозить язык? Не нравится, иди в другой? Мне такой подход категорически не нравится.


      1. navferty
        24.10.2025 15:01

        Чем мешает "перегруженность"?

        По моему мнению, она мешает не столько обычным разработчикам, сколько тем, кто развивает сам язык. Как и с обычным проектом, сложность которого со временем только растёт, добавление очередной фичи связано с возрастающей сложностью ("вам действительно потребуется 2 месяца чтобы добавить эту маленькую кнопочку?!").

        Так и в развитии языка, накопленное наследие концепций и ключевых слов будет мешать добавлять новые фичи, которые появляются в других языках. Мы не знаем сейчас, что это будут за фичи, как например до появления async-await мало кто мог представить, что асинхронный код может выглядеть почти так же как синхронный, без callback hell.

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


        1. posledam
          24.10.2025 15:01

          Совершенно согласен. Архитекторам языка приходится искать компромиссы между "давайте засунем всё!!" и "ничего не трогаем!!". Язык вместе с развитием устаревает, это неизбежно. Новые языки появляются, которые учитывают богатый опыт других языков, но не обременены грузом легаси и поддержки, с ними приходится конкурировать.

          Поэтому время покажет. Но основной мой вопрос не стратегический, к чему приведёт всё это в далёком будущем, а сейчас. Сейчас новые фичи действительно помогают, я ими пользуюсь, мои команды пользуются. Я не могу согласиться с тезисом "мешает", потому что помех я не вижу.


      1. Vedomir
        24.10.2025 15:01

        >Никто не заставляет пользоваться всеми фичами языка.

        Если работаешь один и только со своим собственным кодом - то никто.

        А если в команде и/или приходится чужой код модифицировать - то именно что заставляют.

        Как вы думаете, какой случай чаще встречается в профессиональной разработке?


        1. posledam
          24.10.2025 15:01

          Я опираюсь на свой личный опыт и опыт моих команд. Нет с этим проблем. Ну нет, не сталкивался, зачем выдумывать проблемы на ровном месте? Давайте на конкретные кейсы что ли посмотрим, а не делаем далеко идущие выводы: ой, как же так? Как же разработчик разберётся-то? Увидит field и всё, ступор?


          1. Vedomir
            24.10.2025 15:01

            Сразу и к этому и к соседнему комментарию - я про конкретные фичи ничего не говорю, я про общую логику выражения "не нравится не используй", оно в командной работе неверное вне зависимости от того, C# это, C++ или использование правильного билда в мультиплейерной игре или там аддонов в WoW.


            1. mvv-rus
              24.10.2025 15:01

              Выражаю согласие. Программист отличается от чукчи из анекдота, который "чукча - не читатель, чукча - писатель" тем, что он, в значительной мере, как раз-таки читатель. И читать код с использованием новых функций ему таки придется.


        1. monco83
          24.10.2025 15:01

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


    1. stepagrus
      24.10.2025 15:01

      Вы, наверное, никогда не писали Desktop UI приложения по MVVM. Использование INPC вынуждает писать много boilerplate кода в свойствах. Для решения этой проблемы и запилили field. Жить стало веселее и код стал лаконичнее


      1. chegeras
        24.10.2025 15:01

        эта проблема уже давно решалась сниппетами и писание boilerplate кода заменялось нажатием Tab+Tab


        1. dephonica
          24.10.2025 15:01

          А читание не заменялось.


    1. Denis535
      24.10.2025 15:01

      Есть прикол, что компилятор может неявно создавать копии readonly структур, чтобы гарантировать их имутабельность. И особенно прикольно, если это происходит в цикле...

      И все IT в такой же ж***( Много новых языков и каждый со своими тараканами.


      1. vvdev
        24.10.2025 15:01

        Есть прикол, что компилятор может неявно создавать копии readonly структур, чтобы гарантировать их имутабельность. 

        Такого прикола нет, есть прикол с не-readonly структурами в readonly контексте.

        Читайте документацию, она прикольная.


      1. monco83
        24.10.2025 15:01

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


    1. monco83
      24.10.2025 15:01

      А с моей точки зрения field - самое удачное нововведение в новой версии.


      1. mvv-rus
        24.10.2025 15:01

        Вообще-то, field как псевдоним для значения автоматического свойства - это условность того же типа, что и как псевдоним неявного параметра value в методе установки значения (setter) в свойстве вообще.
        Корень проблем с field - он в самой идее автоматических свойств. КТорая идея есть неоднозначная. Может быть, исходя из концептуальной целостности, их делать было и не надо, но уж больно они удобны! А уж когда есть автоматические свойства, то без field неудобно.


    1. QweLoremIpsum
      24.10.2025 15:01

      Просто язык многофункциональный на нем можно писать и бек и фронт(razor,blazor) и десктоп и мобилки и тд и тп (и на микроконтроллерах вроде тоже можно). Поэтому если вам какое то фича/кейворд кажется излишним, возможно тем кто пишет, например, на блазоре оно экономит кучу времени


    1. aw350me
      24.10.2025 15:01

      если речь про field из бета 13 и релиза 14 версии, то это он из лучших нововведений априори. То, что в вашей узкоспециализированной среде оно не пригодилось никак не отменяет того упрощения, которая эиа фича внесла тем, для кого она вводилась


  1. danilenko-a
    24.10.2025 15:01

    Конечно, есть ещё, на что побрюзжать.

    Да, есть: В Вашей .Net-библиотеке немалая часть функциональности в статических классах.


    1. holgw
      24.10.2025 15:01

      И какие проблемы это создает?

      Если очень нужно отвязаться от реализации, то никто не мешает вызов статических методов вынести в отдельный класс и закрыть его интерфейсом.


    1. monco83
      24.10.2025 15:01

      >немалая часть функциональности в статических классах

      Код не смотрел, но мне это сразу нравится. Неужели замшелые IT-евангелии 10-ых годов до сих пор котируются?


  1. ArtemKonkin
    24.10.2025 15:01

    Как же понимаю автора)

    Я в универе в восторге был от С++. В будущем это очень повлияло на выбор постоянного языка программирования - C# зашёл как родненький (пробовал Python, JS, Java - всё не то).

    Ничего лучше C# так и не встретил. ❤️


  1. MVMmaksM
    24.10.2025 15:01

    Хорошо, что язык развивается, плохо, что он превращается в c++. Это увеличивает порог входа для новичков и приведет к тому, что язык будет терять популярность, и к тому, что один разработчик не сможет понять код, написанный другим разработчиком.


    1. posledam
      24.10.2025 15:01

      Почти все фичи интуитивно понятны. Многие фичи имеют редкое или специфическое применение. По моему опыту, понять код чаще всего (намного-намного чаще) мешает не какая-то там фича языка, а сам код, потому что писать хорошо читаемый и сопровождаемый код довольно не просто для новичков и даже для бывалых.


      1. mvv-rus
        24.10.2025 15:01

        Почти все фичи интуитивно понятны.

        Меня не устраивает это приблизительное знание уровня "интуитивно понятно". Я лично чувствую себя некомфортно, когда приходится основывать свои выводы на таком вот зыбком основании. Я предпочитаю правдоподобным предположениям точное знание. Поэтому использование в коде незнакомых мне "фич" (то есть, дополнительной функционаьности) мешает этот код читать: из-за них я не уверен, что все понимаю правильно. Ну да, из-за такого подхода мне сложнее заниматься современным ритуальным программированием во всяких там фреймворках, использовать где-то когда-то узнанные ритуалы без понимания, как и почему они работают - мне так некомфортно.

        И у меня есть подозрение, что я не один такой - судя по обескураживающей многих любви собеседующих, которые часто - программисты с немалым опытом работы, выяснять у соискателя наличие какого-то там "понимания, как оно работает", а не просто знания необходимых для работы ритуалов.

        PS Читаемость кода - понятие субъективное, зависящее от того, кто читает. Потому что есть разработчики, у которых код, написанный в непривычном стиле, вызывает серьезный дискомфорт (видел в комментариях к недавней статье), а есть такие, которым "Мне всё равно, какой у вас код-стайл".


        1. posledam
          24.10.2025 15:01

          Я немного подушню, простите.

          Я предпочитаю правдоподобным предположениям точное знание. Поэтому использование в коде незнакомых мне "фич" (то есть, дополнительной функционаьности) мешает этот код читать: из-за них я не уверен, что все понимаю правильно.

          Из этого как будто следует, что C# должен остановиться сразу после первого выпуска языка. Ну где-то в районе NET 1.0, там дальше опасно становится. Новые фичи = сложно читать, нервяк и сгорание.

          Далее. Библиотеки и фреймворки, тоже не имеют права выпускать какие-то новые фичи после первого выпуска. Только багфиксы. Значит, мы должны сидеть на первом ASP.NET, не дай боже кто-то увидит что-то новое, это же страшное дело.

          Далее. Какие-то кубернетесы наворотили, надо жить и дальше на виртуалках под IIS, потому что всё это мешает читать код. И понимать его. Конфиги какие-то придумали в appsettings.json, нормально же было в Web.Config. Всё это неимоверно усложняет не только чтение, но и понимание кода, и дальнейшее развитие. Каково это разработчику с проекта ASP.NET 1.0 под IIS перейти сейчас на (караул) в разработку под Linux? Это натуральное издевательство над программистами.

          Ладно, теперь серьёзно. Я вот все комментарии в этом топике прочитал и не только здесь, негатив есть и много. Но хоть один бы кто показал какой-то пример. ДО/ПОСЛЕ и показал, что вот это пипец приносит проблемы. Ну хоть один жалкий пример.

          Я на практике проблем никаких не вижу, осваиваем новые фичи, получаем профит. Не помню ни одной жалобы, что дескать вот этот код непонятен от разработчиков. Хотя вопросы были "правильно ли я понял" и обсуждения, это длится крайне короткий промежуток времени. Мы же инженеры, а не лаптями щи хлебаем. Почему для нас это должно приводить в состоянии паники и отторжения?

          Ну мир не стоит на месте. Всё меняется. Правда. Такова жизнь блин. Так во всех сферах жизни. И каждый год одно и то же, любое изменение = негатив. Почему? Давайте хоть примерчик проблемы. Это было бы как минимум полезно.

          Критика каких-то конкретных фич, это уместно. Есть к чему докопаться. Но позиция, давайте остановимся, замрём, заморозим — я категорически не согласен. Если такое произойдёт в C#, это будет стагнация, и лично я точно сменю язык и платформу, мне развитие нужно, я ещё не старпёр, с которого сыпется. Когда-нибудь это случится, уверен, но не сейчас.


          1. mvv-rus
            24.10.2025 15:01

            Из этого как будто следует, что C# должен остановиться сразу после первого выпуска языка. Ну где-то в районе NET 1.0, там дальше опасно становится. Новые фичи = сложно читать, нервяк и сгорание.

            Не следует. Всё хорошо в меру. Некоторые новые функции крайне полезны, async/await как пример - я хотел бы такую возможность во времена Win3.x, когда, чтобы не заставлять пользователей долго созерцать песочныечасы, надо было на месте, где теперь await, запускать аж вторичный цикл обработки сообщений.
            Но каждая вещь имеет две стороны. Добавление новых возможностей в язык и библиотеки - тоже. Лучшее - оно, как известно, враг хорошего.

            Далее. Какие-то кубернетесы наворотили, надо жить и дальше на виртуалках под IIS, потому что всё это мешает читать код.

            И виртуалки - их тоже наворотили. Я отлично помню время, когда виртуалки на x86 были стильно-модно-моложежными. Но не для всех, например - не для меня, я-то с IBM VM/SP начинал. И IIS со своим ISAPI (не говоря уж о модулях) тоже не сразу появился, так что за образец старых добрых времен следует принять, наверное Apache с CGI. Кстати, до сих пор не понимаю, зачем IIS на виртуалках запускать надо было - в нем запуск нескольких приложений в родном режиме вполне прилично жил, это я вам как тогдашний администратор такого хозяйства говорю.

            Конфиги какие-то придумали в appsettings.json, нормально же было в Web.Config

            Из этого подозреваю, что лично вам с XML - который есть язык для машин, не для людей - мучиться не приходилось. С JSON как-то по жизни сразу проще стало.

            Но хоть один бы кто показал какой-то пример. ДО/ПОСЛЕ и показал, что вот это пипец приносит проблемы.

            Все эти проблемы субъективны. И, боюсь, что замеры изменения скорости чтения кода на репрезентативной выборке разработчиков никто провести так и не удосужился. Так что доказательства тут - они все с пометкой IMHO. Как собрать объективные доказательства - я выше написал, но не думаю, что кто-нибудь этим заморочится.

            А ещё все эти проблемы преходящи. Я вот, в момент перехода от входного языка .NET 4.5 на входной язык .NET Core испытал немало дискомфорта от чтения кода ASP.NET Core(результатми коего чтения я поделился в одной из первых своих статей) - команда разработки ASP.NET Core очень любила всё стильное, модное, молодёжное (и до сих пор, кажется, любит). Но потом - ничего, втянулся, как тот котёнок, что пылесоса боялся.

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

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

            Но позиция, давайте остановимся, замрём, заморозим — я категорически не согласен.

            Я тоже. Но ещё я не согласен с тем, что добавление новых функций или возможностей (слово feature переводится именно так) в язык - это безусловное благо: благо-то оно, может, и благо, но - весьма условное: лучшее - враг хорошего. Нужен баланс. А ещё мне не нравится то, что добавление новых возможностей часто вызвано явно маркетинговыми соображениями, которые мне чужды - у меня нет задачи продать C# - и которые явно смещают скорость ввода этих возможностей от баланса.


            1. posledam
              24.10.2025 15:01

              Все эти проблемы субъективны. И, боюсь, что замеры изменения скорости чтения кода на репрезентативной выборке разработчиков никто провести так и не удосужился.

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

              Поэтому хочется всё же чётко провести границу: это просто естественный дискомфорт, связанный с изменениями, или конкретные проблемы?

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

              Да, понимаю. Более того, я понимаю, что это не бесплатное удовольствие. Но мы инженеры, а профессия разработчика подразумевает постоянное обучение и развитие. Не каждый на это способен, это умственный труд, который (пока) достойно оплачивается.

              Вы согласитесь, если вам дадут какой-нибудь фреймворк, среду разработки, и вот это вам на ближайшие 10-15 лет. Ни шагу в сторону, ни-ни! Я -- нет.

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

              Так и переход на Linux, в контейнеры, эти соображения практические, ради выгоды, а не ради общего блага человечества :)


              1. mvv-rus
                24.10.2025 15:01

                Так и переход на Linux, в контейнеры, эти соображения практические, ради выгоды, а не ради общего блага человечества :)

                Я сейчас ограничиваюсь исключмительно C#. Linux и в целом история того, как технически более совершенные коммерческие Unix пали под его натиском (и причем тут IBM) - это я здесь обсуждать не хочу, оно тут не при чем. Особенно касательно новых функций - тут вообще мимо.

                А хочу я остановиться на следующем.
                а) Ценность (экономический эффект) от введение новых функций не очевидна и требует обоснования. В каждом конкретном случае. Обоснования нет. Обоснования обратного утверждения, впрочем - тоже. Так что здесь предмет аргументированной дискуссии IMHO отсутствует.
                б) Введение новых функций зачастую вызвано посторонними соображениями, а не экономическим эффектом (имеется в виду - для отрасли в целом).
                в) Издержки от введения новых функций перекладываются на работников, зачастую (но не всегда) - без адекватной компенсации.
                г) Очень часто это, якобы, новое - это старое но со взглядом с другой стороны, c которой раньше просто смотреть было не модно. Но это IMHO.


                1. posledam
                  24.10.2025 15:01

                  Обоснование имеется, по каждой фиче велась долгая дискуссия, начиная от proposal, до описания эффекта. Или есть ощущение, что там у кого-то почесалось, и внезапно появляется новая фича. Просто так? :)


                  1. mvv-rus
                    24.10.2025 15:01

                    Ни в одном обсуждении я не видел обоснования их экономического эффекта. Обсуждалась обычно чисто техническая сторона.


            1. holgw
              24.10.2025 15:01

              Вы почему-то не видете другую сторону этого процесса - трудозатраты на освоение новых возможностей.

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

              Ну и в конце концов, если подумать, какие такие фичи появились в C# (за последние 15 лет, например), чтобы их освоение занимало какое-то существенно время? Я могу только появление async\await вспомнить как пример такой сложной фичи. Но я не думаю, что кому-то в голову придет выкинуть её из языка.

              И вы же предлагаете лишить других разработчиков потенциально полезных для них возможностей, прикрываясь каким-то абстрактным "ну нужно чтоб баланс был". Так а может текущий темп развития и соответствует этому самому балансу? Так что это вообще не аргумент. Приведите тогда хотя бы пример фич, которые реально портят вам жизнь, чтобы был хоть какой-то предмет для обсуждения.


              1. mvv-rus
                24.10.2025 15:01

                Ну а вы игнорируете факт того что новая функциональность появляется не просто так, для того что бы закрыть какие-то вполне конкретные проблемы разработчиков.

                Я не игнорирую.Я всего лишь указываю, что каждая вещь имеет две стороны. Указываю конкретно автору предыдущего комментария: он тут пишет так, будто он эту сторону не видит.

                И вы же предлагаете лишить других разработчиков потенциально полезных для них возможностей, прикрываясь каким-то абстрактным "ну нужно чтоб баланс был".

                Не предлагаю. А баланс - его нужно оценивать конкретно, для конкретных случаев. Но оцениивать нужно, а не проталкивать идеючто новое - оно всегда лучше. Помнить, что лучшее - враг хорошего. И никого я ничего не лишаю.В конце концов, другие разработчики могут выбирать другие средства, так что лишить их я ничего не могу. Мне не нравится, что новые возможности вводят не разработчики - пользователи продукта, а его производители, тем самым - навязывая эти возможности всем - и желающим их, и не желающим.

                Приведите тогда хотя бы пример фич, которые реально портят вам жизнь, чтобы был хоть какой-то предмет для обсуждения.

                Вы не поняли. Я - человек, а человек - не собака, ко всему привыкает. Вот я и привык. Новые функции вносят сумятицу сами фактом своего появления, регулярного появления. И не нравится мне именно это.

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


                1. holgw
                  24.10.2025 15:01

                  Мне не нравится, что новые возможности вводят не разработчики - пользователи продукта, а его производители, тем самым - навязывая эти возможности всем - и желающим их, и не желающим.

                  Эм, но это совсем нет так -- есть фича реквесты от коммьюнити, их создают как индивидуальные разработчики, так и компании. У вторых, конечно, есть отдельные каналы и больший приоритет (потому что они платят за это деньги), но сути дела это не меняет.


                  1. mvv-rus
                    24.10.2025 15:01

                    Реализуют все равно разработчики проддукта. А компании могли бы делать b fork вместо feature request - и тогда никто бы никому бы ничего не навязывал.


          1. Siemargl
            24.10.2025 15:01

            Оно то может и верно, но 14 версий языка, на мой взгляд, уже перебор.

            Чтобы это не было просто ИМХО, можно сравнить с другими энтерпрайзными ЯП.


            1. Free_ze
              24.10.2025 15:01

              Тем временем Java уже имеет версию 25 и релизится дважды в год.


              1. Dhwtj
                24.10.2025 15:01

                И отстаёт по Шарп по фичам


  1. jakobz
    24.10.2025 15:01

    Мне кажется, пора кому-то написать C#: The Good Parts :) Или сделать какой-нибудь C-бемоль.

    Они идут очень долгой дорожкой от деревянности и многословности джавы к минимализму. Но там так много всего мешается, что не получается ни просто, ни реально минималистично.

    Но у C# есть прям крутая фишка - там можно делать зубодробильные мета-штуки, и прям рядом писать на них тупой понятный код. Можно делать большие и сложные аппы, с серьезными абстракциями, в 10 средних бойцов, и одного крутого лида. Все другое такое не тянет.


    1. onets
      24.10.2025 15:01

      Хм любопвтно. А можно пример с зубодробительными мета штуками?


      1. jakobz
        24.10.2025 15:01

        Да Entity Framework тот же.


  1. Ydav359
    24.10.2025 15:01

    Среди таких чисто "сахарных" нововведений много именно улучшений производительности, так что грех жаловаться. Вспомните, когда вообще последний раз приходилось лезть в unsafe? Из последних нововведений особенно приятна аллокация небольших массивов на стеке.


  1. lightln2
    24.10.2025 15:01

    C# всегда был одним из моих основных языков программирования, и, пожалуй, самым любимым, еще до его официального релиза в 2002 году, когда к нам на мат-мех СПБГУ приходили ребята из Микрософт показать новый крутой язык. Я хорошо помню, как они на наших глазах открыли Visual Studio, написали "Console.", вызвали контекстную подсказку, и ноутбук завис намертво! Его перезагрузили, и со второго раза все получилось!

    Потом я много лет на нем работал (вместе с Java и C++), но где-то после шестой версии он начал терять популярность и уступать яве и Go (хотя вы можете возразить, что Ява всегда была популярнее?). И такое впечатление, на самом высоком уровне в Микрософт было принято решение экстенсивного развития языка. Я помню, я читал тикет про nullable types (известное изменение в семантике языка, делающее все классы по умоллчанию non-nullable), еще до его официального принятия. Там один человек спросил: "Теперь выражение default(T) больше не имеет тип T - вам не кажется, что это не консистентно?" На что представилель Микрософта прямо ответил: "на данном этапе развития языка создание сообщества вокруг него для нас важнее его внутренней непротиворечивости."

    Тем не менее, я признаю, что это было, наверно, правильное решение. Сейчас c# мультипарадигменный, я на нем писал и суровый энтерпрайз с абстрактными фабриками, и супербыстрые числодробилки с System.Runtime.Intrinsics и вычислениями на видеокарте с ILGPU.net, и ad-hoc скрипты как в питоне. Если кто увлекается программистскими задачками, и решает Advent of Code каждый год, знает, что подавляющее большинство их делают на питоне. Я решал их на c# два последних года, и даже пару раз попал на глобальный leaderboard (что лично для меня огромное достижение, так как приходится соревноваться и с competitive programmers, соревнующихся с детства, так и с LLMs, решающих простые задачи за секунды)! Я описал свой опыт использования c# вместо питона на реддите в этой статье.

    Лично мое мнение - современный C# очень недооценен: он по удобству тулинга сопоставим с Ява, по скорости разработки - с Питоном, по скорости компиляции - с Go, по скорости работы - с C++. То ли Микрософт не вполне справились с продвижением языка, то ли это не было для них приоритетом...


    1. Siemargl
      24.10.2025 15:01

      Лично моё мнение, своими метаниями МС до хорошего не доведёт.

      Чего только стоят 9 (девять) стандартных библиотек для гуи.

      И "мы добавили ложечку сахара", кто то в проекте, а скорее в сторонней либе, его использовал - и всем надо обновлять тулчейн.

      Стабильность, которая была отличием платформы .Нет, пошла по пи


      1. Vedomir
        24.10.2025 15:01

        Из них хоть одна поддерживает полноценный набор платформ аналогичный Avalonia или Electron, включая Linux?

        Не просто так при наличии всех этих библиотек свои проекты вроде VS Code они на Electron пишут.


        1. Siemargl
          24.10.2025 15:01

          Возможно, и да.

          Вот список

          Вопрос в другом - в какую вкладываться, а какую прекратят развивать?


          1. Vedomir
            24.10.2025 15:01

            Прочитал статью по ссылке, ответа так и не нашел. Какой из них поддерживает Linux?

            Там вообще очень странные советы даются " If you're a .NET developer, you can leverage those skills and Visual Studio's UI designer for both Windows Forms and WPF applications."

            В 2024 году советовать WinForms? Я много приложений на ней написал, лет 20-30 назад это была классная технология, но сейчас она давно и бесповоротно мертва.

            Вы вот этот список имели в виду?

            • WinUI 3: The latest UI framework that lets you create beautiful, fast, and fluid Windows apps.

            • UWP: The UI framework that lets you create universal Windows apps that run on many types of Windows devices.

            • WPF: The UI framework that lets you create rich, powerful Windows desktop apps using .NET and XAML.

            • Windows Forms: The UI framework that lets you create traditional Windows desktop apps quickly using .NET.

            • .NET MAUI: The UI framework that lets you create cross-platform desktop and mobile apps using .NET and XAML.

            • Uno Platform: Use your knowledge of UWP and WinUI to build apps for any platform.

            WinUI - нет, UWP - нет, WPF - нет, WinForms - нет, MAUI - полгода-год когда я еще интересовался - нет.

            Uno - сторонняя разработка.

            При этом из этого списка - UWP - мертва, WinForms - мертва, WPF - мертва. Живы только WinUI3 но она только под Windows, что означает в наше время узконишевое решение и MAUI.

            Остается только MAUI который хотя бы мобилки и MacOS поддерживает. Но десктопный Linux многим сейчас нужен, хоть и тоже узконишевое решение.

            Есть ли крупные проекты от самой MS написанные на нем?

            VS Code они написали на Electron, Teams - на React Native.

            Новые компоненты самой Windows на WinUI3.


            1. Siemargl
              24.10.2025 15:01

              Вот и я говорю - развели бардак.


    1. Kingas
      24.10.2025 15:01

      Абсолютно согласен. Только, что они достаточно поздно перешли в cross-platform. Плюс когда он был Windows-only, то могу предположить, что кто-то мог не любить язык из-за того что был проприетарный runtime.

      Но и сейчас сложнее догонять других. Нынче слишком популяр стал JS, как один язык на всё. При это такие языки имеют ряд особенностей и обходных путей, чтобы работал более менее эффективно. Ну а некоторым в кайф не думать о типах, и соответственно об производительности.

      Так же у dotnet runtime нормальная версионность и выбора runtime, никогда не было проблем в множестве версий dotnet. После C# смотрю на всякие nvm, rvm, pyenv как на решение проблемы, которую могли бы решить изначально.


    1. Melanchall Автор
      24.10.2025 15:01

      Полностью с вами согласен. В целом, C# так или иначе присутствует в пятёрке ну или как минимум десятке самых популярных языков. Но да, до уровня того же Python ему далеко. Вы подняли любопытную тему.

      Мне кажется, важно ещё то, что сам .NET был очень долго привязан к Windows (хорошо хоть в MS одумались). Да, был Mono, был Xamarin. Но сторонние поделки не так сильно поднимают популярность, как действия со стороны самих разработчиков языка.

      Ещё я только что осознал, что у C# нет вменяемого логотипа, там просто многоугольник с надписью C#. У Python две змейки в виде плюса, у Java чашка кофе, у Go милый зверёк, у Rust велосипедная звёздочка на пять болтов. Мелочь, конечно, но тоже может влиять.

      И да, тоже ежегодно решаю задачки Advent of Code, использую его как полигон для опробования новых фич языка. Правда, в leaderboard не попадал никогда. Да и вообще, все задачи (обе части) решил только в 2020-м. Я тоже сделал себе набор полезных методов, а C# использовал сразу. В целом, олимпиадные задачки (а AoC всё же больше к ним тяготеет) мне даются непросто. В этом году, думаю, в лидерах будут сплошь LLM-ки.


      1. posledam
        24.10.2025 15:01

        А зачем C# логотип? :) Т.е. это может было бы и неплохо, но само название "C#" оно уже уже сам себе типографический логотип, как "C++".


        1. Melanchall Автор
          24.10.2025 15:01

          По такой логике и Go вполне кратко, ёмко и логотипно. Но вообще на ваш вопрос "зачем" ответы будут субъективные и их будет много. Ну вот мне кажется, что даже и такие вещи могут иметь значение – узнаваемый символ. Но могу ошибаться.


    1. Dhwtj
      24.10.2025 15:01

      где-то после шестой версии он начал терять популярность

      Как раз версии 7,8,9 принесли очень много полезной функциональщины. А вот дальше что-то развитие идёт быстро, но не туда.


      1. mvv-rus
        24.10.2025 15:01

        Как раз версии 7,8,9 принесли очень много полезной функциональщины.

        Слово "функциональщина" тут правильное. Главное тут - не путать ее с функциональным программированием, с идеей, что можно построить преобразование (скажем нестрого) множества входных значений в множество результатов. Потому что в C# у компилятора нет для этого основы - понятия чистой функции. Нет, лично вы написать чистую функцию сможете - это не запрещено, - но вот контролировать отсутствие побочных эффектов вам придется самому, вручную: компилятор вам в этом - не помощник.

        Просто не надо вообще рассматривать делегаты как значения типа "функция". Делегаты - это про другое, лично я их интерпретирую как своего рода "программирование будущего", как операции, которые будут выполнены когда-то потом, при наступлении определенных условий.

        развитие идёт быстро, но не туда.

        Ну да - не туда, куда вам хочется. Но вас, как я понимаю, никто не заставляет использовать именно C#. Используйте другие языки, может быть, они вам понравятся больше.
        В целом же я соглласен с основным посылом статьи: нельзя объять необъятное, и языку, чтобы не потерять обозримость, легкость обучения и использования, стоит оставаться компактным, не тащить в себя лишние, плохо совместимые идейно друг с другом возможности.


        1. Dhwtj
          24.10.2025 15:01

          Да, делегаты не обязаны быть чистыми функциями (чтобы вызов был эквивалентен замене на уже известный результат), комбинируемыми, идемпотентными.

          Но чтобы сделать именно такие в c# 7,8,9 появилось инструменты

          • Records

          • Static local functions, static lambdas (запрещает захватывать контекст)

          • Nullable reference types

          Это не гарантии, но уже неплохо


          1. mvv-rus
            24.10.2025 15:01

            но уже неплохо

            Плохо. Потому что для получения преимуществ от FP нужны гарантии. А их с нужной стороны - описания параметров - нет (static для локальной функции или лямбды - это со стороны описания самой функции, того что станет аргументом при вызове). Ну, а все остальное - это вообще не про FP.
            А без этих преимуществ FP не нужен - никому, кроме его фанатов.


            1. Dhwtj
              24.10.2025 15:01

              С этими преимуществами - ограничениями тем более не нужен.

              Судя по популярности языков программирования бизнес хочет набирать программистов с 2х недельным опытом


              1. mvv-rus
                24.10.2025 15:01

                Судя по популярности языков программирования бизнес хочет набирать программистов с 2х недельным опытом

                Да. И когда такое получается, то в этом чувствуется поступь прогресса. Как чувствовалась она при промышленной революции в Англии 200 лет назад, когда станки позволили заменить опытных мастеров-ремесленников необученными работниками, буквально, детьми.

                И в результате ведь всё общество в целом оказывается в выигрыше: трудоемкость продукта снижается за счет замены сложного труда на простой.

                Но мастерам обидно, да - бабло начинает идти мимо них. Иногда - обидно до смерти, как в случае с индийскими ручными ткачами.

                PS Ваше признание, что FP не нужно, оно только зря топливо жрет - ценю.


                1. Dhwtj
                  24.10.2025 15:01

                  FP и вообще качественная инженерия для общества в целом полезно, но

                  1. Потребитель болен FOMO

                  2. Компании, выбившись в лидеры выжигают вокруг себя поляну, в которой больше ничего не растёт

                  3. Менеджеры больны клиповым мышлением

                  В результате, на исполнителя в виде денег часто ничего не просачивается


    1. W_o_o_f
      24.10.2025 15:01

      Тем не менее, я признаю, что это было, наверно, правильное решение. Сейчас c# мультипарадигменный,

      Мультипарадигменность в С# несколько меркнет на фоне того что придумали в индустрии за последнее время. В данный момент "OOP-first" лучше ему подходит.

      он по удобству тулинга сопоставим с Ява,

      Ну так ява это не эталон, и увы, работа на мсбилд с тонной магического XML по эргономике отстаёт от карго, build.gradle.kts, да даже того же sbt.

      по скорости разработки - с Питоном

      Основная фича питона это чистый синтаксис без {}<<<<<,,,,,,,>>>>>>(())[]; Это может казатся незначительным, однако чем меньше глаз делает саккад для пробежки по коду - тем проще его читать. Кроме того, есть большое количество парных скобок, пустых строк и табов по 4 пробела тоже не убавляет движения глаз. Можно сказать что "типов нет", окей, есть скала по соседству которая с 3 версии имеет подобный питону синтаксис, и систему типов получше той что дала MS.

      по скорости компиляции - с Go,

      Не особо понимаю столь сильную заботу о ней. У меня был проект на ~400к строк скалы(в переводе на другие языки можно смело умножать на 2), что известна своей медленной компиляцией, и полная сборка с 0 с удалением всех кешей, составляла порядка 2:30, а перекомпиляция и запуск несколько секунд. Идея позволяет держать это + ещё пару десятков окон открытыми и всё будет быстро и шустро работать.

      Если кто увлекается программистскими задачками, и решает Advent of Code каждый год, знает, что подавляющее большинство их делают на питоне.

      По той простой причине что большинство это делает для подготовки к алго-собесам в фаанги, и цель решить задачу в срок и ничего больше. Проще всего это делать не тратя время на скобки и точки с запятой, делают они это оправданно. Моё время решения задачек на литкоде сократилось когда я перешёл на брейслесс синтаксис скалы.


  1. Kingas
    24.10.2025 15:01

    Обсуждение фич это полезно. Но дух статьи всё же претензии и вкусовщина.

    Часть это просто про альясы и совместимость, ничего особого чтобы были претензии.

    Больше возможностей ref это же афигенно. Я давно считаю, что C# делали именно так, чтобы выжимать все соки в managed, но при этом конструкции языка не на столько плохо читаемы, как у C++. Так же в отличии от Java, у котрого нету нормального понятия расширяемых value type, и отсутствие примитивов как тип в генериках, и вытекающие из этого проблемы и workarounds. Я бы сказал КОСТЫЛИ языков где нету расширяемых value type (структур).


    1. Melanchall Автор
      24.10.2025 15:01

      А я и не скрываю в статье, что вкусовщина. И шарп я люблю, и переходить на другой язык не желаю. Но всё равно внутри какое-то чувство, что что-то не так... Но повторюсь, я сам нововведения использую. А в разделе про ref подчёркиваю, что это примеры полезных (на мой взгляд) фич.


  1. Kerman
    24.10.2025 15:01

    Я всё жду, когда же завезут yield return IEnumerable. А то приходится форичами пробрасывать наверх )


    1. Melanchall Автор
      24.10.2025 15:01

      Кстати, да :-)


    1. Melanchall Автор
      24.10.2025 15:01

      Запрос на такую фичу, оказывается, существует с 2015-го года.


    1. posledam
      24.10.2025 15:01

      Согласен, очень бы хотелось!


  1. onets
    24.10.2025 15:01

    В целом я медленно перехожу на новые фичи языка. Не все нравится.

    Например v is null лучше чем, v == null. но v is not null слишком многословно, чем v != null

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

    Топ стейтмент не понравились. Теряться ощущение структуры, как и неймспейс или using без обрамляющих фигурных скобок

    Но вот фича когда c# можно использовать как скриптовый язык - мне понравилась, хотя пока не пользовался так активно.


    1. posledam
      24.10.2025 15:01

      Дефолтный метод в интерфейсе как будто покрывается методами расширений. Но методы расширений нельзя переопределить, а дефолтный метод можно. Однако, применение этому пока так и не нашлось лично у меня. Как-то поздно фича заехала, чтобы какие-то решения на базе этой фичи сложились.


  1. Jijiki
    24.10.2025 15:01

    всегда было интересно вот есть

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

    как в сишарпе делают инстанс чтоб не было копирования

    например 100 одинаковых моделек с одинаковыми анимациями, не будем же мы считать каждую анимацию как в первый раз


    1. Alexsey
      24.10.2025 15:01

      Массив в C# - референсный тип. Заранее создайте условный Animation[] и проинстанцируйте один раз, создайте в условном Model конструктор с Animation[] на входе и проблема решена - все Model будут ссылаться на один и тот же объект Animation[] в памяти. Двух-трех-мерные массивы точно так же себя будут вести.


      1. Jijiki
        24.10.2025 15:01

        да спасибо, я паралельно тоже посмотрел, как в С++ почти что


  1. QtRoS
    24.10.2025 15:01

    На 100% согласен, раньше C# был основным языком по работе и одновременно личным предпочтением. Сейчас после всех этих усложнений эту нишу занял Go, и хоть Linq иногда очень не хватает, я все же рад такому переходу, в т.ч. благодаря минимализму языка.


    1. aftertherainbow
      24.10.2025 15:01

      Вообще этого не понял, ничего не мешает писать на c#, как писали на его первых версиях.


      1. QtRoS
        24.10.2025 15:01

        Мне - да, ничто не мешает, но и другим ничто не мешает писать с новыми фичами. Знание языка это такой островок стабильности наряду с базовыми знаниями в Computer science, который со временем не так устаревает, как все остальное. Ибо стандартное для IT "нужно бежать со всех ног, чтобы только оставаться на месте, а чтобы куда-то попасть, надо бежать как минимум вдвое быстрее!" (с) и так грузит заметно - нужно постоянно актуализировать знания в БД, Observability, System design, AI, DevOps, etc. На этом фоне удобно когда есть относительно устойчивый фундамент. Сейчас, к сожалению, я уже не могу сказать, что знаю C# на должном уровне, язык убежал вперед...

        Ну уже конкретно в области мнений - кажется, что C# просто не нуждался в таком количестве фичей. Я со многими не согласен.


        1. mvv-rus
          24.10.2025 15:01

          C# просто не нуждался в таком количестве фичей.
          Тут уже писали в комментариях: язык - не нуждается, а вот разработчики языка нуждаются очень даже: без новых функций ("фич") язык воспринимается старомодным, не стильным, не модным и не молодежным, а потому привлекает к себе меньше внимания. А конкретно в Micrоsoft, в связи со сменой парадигмы с платформенной компании на облачную и взыванное этим, как минимум, снижении активности в продвижении своей прежней платформы Windows Server и повышением вследствие этого роли мультиплатформенности внимание как раз привлечь потребовалось, пусть даже внимание досужее.
          Так что здесь не всё так однозначно.


  1. Bardakan
    24.10.2025 15:01

    А какое развитие языка вы предлагаете взамен? Как apple каждые 5 лет выпускать новый язык (или сильно измененный диалект существующего) и заставлять программистов учиться заново? По слухам следующим будет Rust.


    1. Dhwtj
      24.10.2025 15:01

      Если MS встанет за спиной Rust и будет его продвигать будет прикольно. Особенно, если оплатит переписывание тучи кода библиотек


    1. tester37
      24.10.2025 15:01

      MS могла бы вполне поучаствовать деньгами в таком развитии языка, когда программисты им владеющие имеют радужное настоящее и радужное будущее в рынке, и не за счет того, что их все меньше и меньше а легаси как-то надо поддерживать. И это развитие - не столько про сахар, сколько про соль :) Все актуальные и перспективные ниши чтобы легко можно было закрывать. Но наверное там решили, что сахар - дешевле, а до соли сами кодеры доведут, либ наделают, фреймворков, апишек.


  1. gdt
    24.10.2025 15:01

    Ну хз, бОльшая часть нововведений (может не считая field и scoped ref) легко и непринужденно используется, там где надо, благо всякие решарперы намекают. С другой стороны, никто не заставляет, например для пустой коллекции вы всё ещё можете писать Array.Empty<TValue> вместо []. Проблема имхо высосана из пальца.

    Также рекомендую почитать конспекты LDT, мне думается, что каждая новая фича имеет под собой какое-то обоснование. Я вот трейты жду не дождусь, т к текущий дизайн extension методов мне видится костыльным.


  1. Vedomir
    24.10.2025 15:01

    фича попала на верхние строчки анти-рейтинга нововведений — 40 положительных голосов и 29 отрицательных.

    У меня вызывают серьезные сомнения рейтинги и антирейтинги на основе мнения сотни и менее человек.


    1. Melanchall Автор
      24.10.2025 15:01

      Я с вами соглашусь, но увы, других метрик не нашлось :-( Вообще, было бы очень круто со стороны MS устроить большой опрос по использованию и удовлетворённостью фичами языка. Им бы тоже было полезно: были бы видны потенциальные векторы развития языка.


  1. monco83
    24.10.2025 15:01

    C# - это мой основной язык программирования скоро уже 20 лет. И у меня отношение к новым фичам: лучше да, чем нет.

    Да, не все они сильно удачные, не всегда последовательные. Но, т.к. я пишу на C# постоянно и так же имею возможность постоянно переходить к новым версиям C#, то могу сказать, что писать мне в целом становится приятней и удобнее. Что мне не нравится я не использую, что нравится упрощает мою работу. И если выбирать законсервировать язык или дать ему развиваться так, как он сейчас развивается, то лучше оставить как есть, со всем этим синтаксическим сахаром. Понятно, что развитие никогда не будет идеальным.

    P.S. Лично для меня наиболее крышесносящим нововведением когда-то были лямбда-выражения. Вот это было большое удивление. Ничего, разобрался, привык, сейчас C# трудно без них представить.
    P.P.S. Для меня, наверное, самый раздражающий момент в дизайне языка - это неопределённость с семантикой сравнения. Equals, GetHashCode, ==, equatable-интерфейсы, разные дефолты для классов и структур - чего там только нет. records, новая синтаксическая фича, с одной стороны приносит сюда ещё больше разнообразия, а с другой стороны - сильно уменьшает связанный со всем этим boilerplate.