Pull to refresh

Comments 131

Можете указать в вашем посте, что публикация, вызвавшая ваше возмущение, уже в черновиках (ведь ссылка фактически никуда не ведёт)?

PS: Во время коммента пост выглядел так (возле названия поста в первом предложении нет пометки (уже скрыта, например)

Странное дело, но у меня ссылка работает. Проверил в режиме инкогнито.

У других ребят может не работаь в хроме, но работать в сафари и наоборот

Спасибо за ответ, отправил запрос поддержке.

Номер заявки HLT-FTHXK-341 .

Их ответ: "При попытке перейти напрямую в пост https://habr.com/en/company/skillfactory/blog/585884 из поста https://habr.com/ru/post/586020/, он не открывается. Но если открыть в новой вкладке или вставить адрес в адресную строку, пост открывается."

Ждём.

Хочу сказать в защиту Unity. Как давно вы следили за развитием ветки Mono, чтобы сделать вывод о реализации в нем C#? На движке уже давно используется C# 8 версии и создано множество дополнительных сторонних библиотек через ассеты, которые вносят и без того приятную вариативность при создании игрового приложения. Да, использовать определенные паттерны проблематично, но зачем их использовать, когда есть применение более разумных паттернов для данного контекста; Или вы в своих проектах стараетесь применить более десятка паттернов сразу?! Не завидую я пользователям таких проектов тогда.

Не сказал бы, что ниша C# - backend. Скорее (судя по вакансиям) ниша C# - fullstack. Чисто бэкэндных задач на C# по-прежнему откровенно мало (по сравнению с go и java) и это печалит. Но, надеюсь, в будущем это изменится.

Fullstack это FE + BE. FE на C# это Blazor - он не готов к масс продакшен. BE - то самое место где C# чувствует себя замечательно.

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

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

Так всем по кайфе найти человек-оркестр :)

Ой блин, ну ужас там разница между C#, Java и TypeScript. Сиподобные языки ж все.

Главное — императивные. Вон, с БД всу куда хуже ;): там SQL декларативный — и ничо, все терпят.

IMHO превалирование full-stack вакансий - это скорее желание бизнеса сэкономить. Full-stack конечно неплохо, но всё же приходится объять необъятное и какая-то часть определённо будет страдать: либо бек, либо фронт.

Это называется TShaped Skills

А static в интерфейсах тоже не впечатляет? Или логика такая, что они не успеют похоже его запилить и он в превью останется?

ИМХО, такие фичи просто никто не будет использовать. А если и будут, то вреда много не нанесут

Чем они принципиально отличаются от статиков в классах?

множественным наследованием

А почему бы просто не ввести множественное наследование?
Я, например, на C++ эти самые интерфейсы эмулировал в свое время именно через множественное наследование — от виртуального базового класса (абстрактного или не совсем).

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

Мне не очевидно, зачем разбираться в цепочке наследования в случае виртуального базового класса. Ведь достаточно просто добавить public virtual base_class в список классов, от которых наследуется данный, и все. А если от этого же базового класса было наследование (виртуальное) ещё где-то в цепочке, то с этим уже сам компилятор разберется.

Кажется, вы меня тролите:) Ну не просто так же запретили после плюсов множественно наследование везде. Получается, всем понятно зачем запретили, вам непонятно.

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

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

Там же, вроде, на diamond в мотивации отказа обычно ссылаться принято?

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

Множественное наследование позволяет унаследоваться от двух и более разных классов, имеющих метод с одной и той же сигнатурой. Неоднозначность того, какой из методов становится частью интерфейса производного класса, вроде, и называют "diamond problem". Явное указание вызываемого метода при использовании = "текущая" абстракция. Все остальное порождает ещё бОльший ворох проблем.

Но я тоже не то чтобы великий теоретик, тоже больше по гешефтам.

Но виртуальные-то базовые классы лишены этого недостатка, не так ли?

У виртуального наследования есть недостаток в виде реализации (при наличии полей) — это несколько vfptr в одном объекте, это ненулевые смещения базовых классов. То есть банально сравнить два объекта через object.ReferenceEquals будет в принципе невозможно.


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

Ну а виртуальное множественное наследование при отсутствии полей — это и есть интерфейсы.

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

А вот это физически невозможно сделать :( но мне тоже не хватает

Почему невозможно? Всё "ООП" в чистых С на таком построено.

Тут просто вопрос о целесооборазности тянуть в нерезиновый стек лишние поля с информацией о разметке. Структуры изначально задумывались как сверх-легковесное DTO.

Структуры изначально задумывались как сверх-легковесное DTO.

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

Или инлайнить :(

А как статики то наследуются?

Посмотрите proposal champion на гите. Там достаточно подробно описано.

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

Все так: static abstract и static sealed. Подмешивать поведение можно, мутировать стейт и создавать неочевидные цепочки наследования нельзя.

Я буду еще как. Это ж тайпклассы почти. Супер-нужная мега-недооцененная фича. Дайте еще улучшеный вывод типов для generic'ов и abstract sealed.

Да, с такой точки зрения я не смотрел

Хорошая есть фраза, смысл примерно такой.

Да, фича пилится для 1% разработчиков. Но то, что этот 1% делает, будет потом использоваться остальными 99% разработчиками.

Ну так почему бы напрямую тайпклассы и не ввести? Зачем так?

Тот же вопрос к default interface methods вообще. Может лучше было ввести новую сущность trait?

UFO just landed and posted this here

В proposal champion написано почему решили интерфейсы расширять, а не вводить новую сущность. Там бритва Оккама.

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

P.S. Навеяно Swift. Пришлось делать проект на нём и эти вещи мне понравились

Просто static ещё можно как-то понять и простить. Cамому иногда такого хочется в связке с дженериками. Но там всё прикольней - static abstract и static virtual в интерфейсах... это уже перебор

Да нормас. Там же стейт не наследуется. Так что все ок

UFO just landed and posted this here

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

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

В го зачастую "плохой" код связан с двумя явлениями, оба из которых к самому го прямого отношения не имеют:

  1. Код часто пишут джависты, а они способны писать на спринге джаве даже на фортране. Идеологически чуждый код действительно может смотреться странно и непонятно ;

  2. В го есть тяжёлое наследие в виде большого количества сишников и плюсовиков, которые тоже сильно травмированы своими языками и зачастую вообще не считают нужным думать о качестве кода в смысле читаемости, переиспользуемости и тп, просто по привычке тратя 99% "мыслетоплива" на оптимизации. В итоге иногда получается месиво из однобуквенных переменных и прочей магии и все в одном файле.

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

Спасибо за ответ, хотелось бы послушать подробности:

  1. Как вы управляете зависимостями? DI контейнер через кодогенерацию?

  2. На сколько удобно работать без нативной иммутабельности? Обычно с ростом кодовой базы именно баги в мутациях становятся главной болью

  3. Встречались ли с проблемами отделения бизнес логики от инфраструктуры? Это важный вопрос, посколько реализация паттерна Спецификация крайне многословна (а потому и излишня) в go

  1. Отвечу как происходит у нас. Среди более тысячи микросервисов, зависимости инициализируются и внедряются руками. Один из нагруженных проект 5-летней давности имеет ~500 строчек инициализации разных клиентов, сервисов, хендлеров, крон джоб и прочего. Конечно же, с примесью if err != nil :) Есть возможность использовать кодогенерацию (google/wire), но на моей практике, ее используют только для очень больших приложений.

    Признаться, было неудобно после перехода с ASP.NET на Go, но зато никогда не ловил баги в рантайме из-за регистрации зависимости как Scoped, а не Transient (или наоборот). Не было рантайм ошибок из-за неправильной настройки сервиса. Особенно раздражает в ASP.NET, что, когда скопипастил шаблонный проект, есть нужда поменять Startup.cs и час-два пытаться понять почему у тебя какие-то непонятные исключения при инициализации сервисов. Часто такое было с IdentityServer и иногда с EF. Возможно, я просто неправильно читал документацию, но у меня часто появлялась необходимость зайти на stackoverflow и заучивать в какой последовательности нужно описывать свой startup :)

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

Спасибо, а как вообще ощущение от работы с ЯП "без магии"?

Ощущения смешанные. Без LINQ и обобщенных коллекций иногда неприятно. Зато как легко провалиться в библиотечную функцию или случайный проект, быстро прочитать нужный код, и понять что происходит. Но не без исключений - тот же k8s читать сложно, хотя его писали джависты)

Возможно, именно поэтому :D

В бесплатном Identity Server плохая обработка ошибок внутри к сожалению...

В ASP.Net core 3 добавили возможность валидации DI контейнера, её нужно включать

public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }) // Add a new service provider configuration .UseDefaultServiceProvider((context, options) => { options.ValidateScopes = context.HostingEnvironment.IsDevelopment(); options.ValidateOnBuild = true; });

В ASP.Net core 3 добавили возможность валидации DI контейнера, её нужно включать

… только для дефолтного провайдера. Так что на самом деле, это не в "ASP.NET Core 3", а в Microsoft.Extensions.DependencyInjection.

Ну в Simple Injector самодиагностика сразу была… так что не только:)

  1. Обычно для тестов юзаю DI контейнер, а продовый код - напрямую, руками (можно и кодогенерировать, но если честно нужды не возникает, один файлик на пару сотен строк отлично менеджится руками. Если разрастется, прикручу кодген), чтобы иметь компайл тайм гарантии ;

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

  3. Особых проблем не возникает, обычно я по ddd выделяю инфраструктурный слой, слой приложения и доменный, и связываю их через интерфейсы и реализации. Конкретно спецификацию я использую не очень часто, это правда, чаще просто прячу логику например внутри разных методов репозитория. С переиспользованием кода и всеми ништяками, и тд.

Спасибо,

Выглядит многословно, но "должно работать" :)

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

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

Исключения vs ошибки-значения, конечно, вкусовщина, но в целом внятный самодокументированный интерфейс библиотеки на Go соорудить сложнее.

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

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

Сложность языка не так сильно влияет на порог входа. Я опросил множество молодых ребят и не встретил ни одно джуна, который бы жаловался на сложность синтаксиса. Для них фундаментальные понятия, типа DI, модульного тестирования, оказываются гораздо сложнее, нежели оператор switch

Оригинальный способ сбора статистики о пороге входа только у тех, кто его успешно преодолел ;-)

"Нам не нужны неудачники" :)

Насколько я понимаю, отрасль разработки ПО не может позволить себе такой поход: ведь нехватка кадров достаточной квалификации — это одна из ее основных проблем, не так ли?
PS Нет, лично я как программист (хоть и не настоящий) не против того, чтобы порог вхождения был побольше, а зарплаты — повыше.
Но ведь общество в целом должно как-то эти зарплаты потом компенсировать?
с тяжелым наследием Александреску
«Лично я ничего не понял, а поэтому оно тяжелое и вообще ненужное», так?

Ну хз, у меня как не инфраструктурный код, так сплошной Александреску. Зря вы так про Андрея.

Фраза "укушенный Александреску" существует не зря :)

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

Странно, не у всех работает

А именно ссылка из коммента выше работает? Потому что при попытке перейти напрямую в пост https://habr.com/en/company/skillfactory/blog/585884 из поста https://habr.com/ru/post/586020/, как локаль в URL подставляется и ru, и en, получается ссылка именно вида https://habr.com/ru/en/company/skillfactory/blog/585884/ , в этом всё и дело.

  • P.S. не очень корректно обвинять автора в узколобости, так его основной опыт работы с C# в контексте Unity, а для игр очень плохо подходят концепции функционального программирования

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

  1. Иммутабельность плохо уживается с изменчивостью игрового мира

  2. Если мы будет строить pipeline в каждом цикле game loop, то не факт что сможем "уместить" все в один кадр

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

    1. А вот если писать императивно, но с async/await или корутинами, получается даже удобнее

Самое неприятное, что ФП стиль неплохо ложится на многие тулы в Unity (то же DOTween), но сложно это жкстраполировать на все.

Про перфоманс не буду говорить, а то захоливаримся:)

UFO just landed and posted this here
ФП не означает иммутабельность. Современный ФП про контроль эффектов в типах, и мутабельность там ничему не противоречит.

Но как с этим в C#? AFAIK — никак и не планируется.
А без этого, с одними делегатами как воплощением first class function, нельзя ни в чем быть уверенным. И, оборачивая переданный в качестве параметра делегат в свой, чтобы сделать, к примеру, композицию, вы не можете быть уверены, что вызов этого вашего делегата не отдаст, условно, команду начать ядерную войну через делегат-параметр.

А вот если писать императивно, но с async/await

Я такое из коробки видел только в Paradox/Xenko/Stride, в Unity вроде бы через генераторы извращались. Буду признателен за ссылку.

Можно раскрыть тезис про «для игр очень плохо подходят концепции функционального программирования»?

Есть такой очень умный человек — Эрик Липперт. А комиксы рисуют почему-то про Джона Скита... Серьёзно, можно зайти на StackOverflow, открыть его страницу и начать читать ответы как статьи. Хотел бы я уметь ТАК излагать мысли.

Так вот, он, по-моему, приводит замечательный пример pure FP в игрострое:

Because all those advantages are also disadvantages.

>Stateless programs; No side effects

Real-world programs are all about side effects and mutation. When the user presses a button it's because they want something to happen. When they type in something, they want that state to replace whatever state used to be there. When Jane Smith in accounting gets married and changes her name to Jane Jones, the database backing the business process that prints her paycheque had better be all about handling that sort of mutation. When you fire the machine gun at the alien, most people do not mentally model that as the construction of a new alien with fewer hit points; they model that as a mutation of an existing alien's properties.

Как человек, который недавно только решил поизучать C# могу сказать, что у меня действительно некоторый функционал вызывал недоумение. Вроде наличия делегатов / ламбда-функций / анонимных-методов. Но оно не то чтобы непонятно как, скоре непонятно почему сразу не добавили функции как объекты первого рода (если бы язык с нуля писали то возможно так и было бы). Или зачем нужны out параметры при наличии возможности возвращать несколько значений, но out параметры появились раньше, странно было бы их удалять. Null-safety тоже вот зачем-то (на самом деле понятно зачем) сделали через warning, а не через ошибку компиляции.

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

Вы можете добавить pattern-matching в switch, но не можете удалить старый switch. В лучшем случае задеприкейтеть его и удалить лет через 10.

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

Они очень часто используются для вызова С/С++ библиотек. А это то на чем живет dotnet внутри. Плюс они уже прижились в разных API-аях те же TryParse/TryGet и т.д.

Вы можете добавить pattern-matching в switch, но не можете удалить старый switch. В лучшем случае задеприкейтеть его и удалить лет через 10.

Они все-таки не однозначны. pattern-matching switch не может заменить все старые switch.

Null-safety тоже вот зачем-то (на самом деле понятно зачем) сделали через warning, а не через ошибку компиляции

Потому как ломает много кода, по желанию легко превратить предупреждения в ошибки: .editorconfig

Удалять функционал сильно сложнее, чем добавлять.

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

Ну есть такой момент… многие уже начали говорить, что C# идёт по кривой дорожке C++. Однако команда C# тратит просто очень много времени на дизайн и анализ. Будьте уверены, что все новые фичи продумываются от и до.

UFO just landed and posted this here

А как джависты про Котлин вообще: с удовольствием переходят или есть те, кто "фу-фу-фу эти ваши лямбды, сложна-сложна непонятна, лучше уж на восьмерочке оставаться"? Понятно, что люди разные, но если взять среднюю температуру по больнице?

Переходят постепенно. Kotlin медленно но верно отжимает и backend разработку.

Как джавист с опытом скажу: с семёрки (привет Android!)/восьмерки приятнее переходить на Kotlin, чем на Java 11++ (при условии, что используем новый функционал).

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

А то что статиков нет и есть корутины не вызывает дискомфорта?

Статики - есть. Корутины - наоборот очень комфортно (в Java немного подзадалбывает всем в экзекюторах ручками управлять), в С# сильно не хватает.

Ну все-таки есть object и companion. Да, я знаю про @JvmStatic,но мы говорим про язык, а не байткод. async/await, yield чем не корутины в C# или вы свои корутины пишете когда-нибудь? Если пишете, очень интересно узнать какие real-world scenarios для этого. Из очевидного - arrow, но я не уверен, что все понравятся конструкции вида:

result {
  val smth = r.bind()
  //...
}  

Лично мне нравятся. Я бы еще и инфиксную нотацию или оператор для bind добавил, но вот студенты жалуются :)

В меня простите, но вот эти ваши откровения:

async/await, yield чем не корутины в C# или вы свои корутины пишете когда-нибудь?

мне говорят о том, что вы слабо понимаете что такое корутины и что такое Task в C#.

Если вам интересен real-world scenario - то я, в том числе, на корутинах писал middle-ware - т.е. сервер, который собирает данные с активных и пассивных датчиков и предоставляет их через REST службу потребителю. Корутины (да, "самописные") сократили изначально джавовский код в разы, при этом в разы подняв его читаемость и исключив падучесть.

Из очевидного - arrow, но я не уверен, что ...

??? Вас вообще куда понесло-то?

мне говорят о том, что вы слабо понимаете что такое корутины и что такое Task в C#.

Ну просветите, по мне разница только в том что в Kotlin концепт обобщенный, а в C# гвоздями прибили ключевые слова. В обоих случаях CPS получаем. Опять же async/await можно же перебить на свои awaiter'ы, просто это не нужно никому.

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

Ну т.е. вы описали типовой сценарий использования акторов. Т.е. скорее всего можно не писать свои корутины, а использовать существующие.

??? Вас вообще куда понесло-то?

Я об этом.

Ну просветите...

Не нанимался.

Для того чтобы начать - корутины это не про стиль написания кода и не про ключевые слова. Это способ организации ("параллельных") вычислений. И да, в Kotlin тоже "прибиты" ключевые слова (точнее слово - suspend). А CPS - можно вообще в однопоточном коде безо всякой асинхронности организовать. С корутинами, конечно, продолжения связанны но это всё-таки другая опера.

Т.е. скорее всего можно не писать свои корутины <...>

Каково ваше определение фразы "писать свои корутины"? Свой корутинный фреймворк что-ли? Конечно я его не писал.

>??? Вас вообще куда понесло-то?

Я об этом.

Так и я об этом. Куда вас понесло и зачем?

И самое главное, как ваши аргументы относятся к вашему изначальному тезису, что в Котлине "дискомфортно" из-за корутин?

>>C# для GameDev (в Unity он смотрится откровенно плохо)
В статье про манипулятивные техники используются манипулятивные техники. Вот это поворот.

Чем плох шарп в юнити? После того как появился Burst (трансляция IL/.NET в LLVM) и Jobs system (многопоточный код), то о каких-либо проблемах с производительностью можно забыть. С каждой версией Unity всё большее количество апи поддерживает работу с NativeContainer. Даже если не утруждать себя написанием многопоточного кода, а только пропустить тяжёлый метод через Burst, можно получить буст производительности в 10-20 раз. Также в методах, которые невозможно вынести из основного потока можно использовать unsafe context. В результате на выходе получится игра сравнимая по производительности с аналогом на c++.

Осталось переписать весь движок с поддержкой новых Jobs, Burst и ECS. Я вообще не понял зачем они решили доказать что c# может быть такой же быстрый как с++, и добавили туда Burst (трансляция в LLVM), NativeContainer'ы (освобождение памяти или утечка) и оперирование этим всем с указателями в unsafe. Могли сразу просто прямую поддержку плюсов впилить да и всё на этом.

Ещё эти Jobs + ECS с просто тьмой бойлерплейта, для того, чтобы просто проитерировать компоненты в IJobChunk надо сначала объявить их хенделры как поля, потом получить списки с компонентами у чанка, а потом уже по индексу получить компонент, в итоге если тебе надо использовать в Job'e к примеру, 5 компонентов, у тебя уже 15 строк просто для того чтоб просто их получить.

Может статью напишу про то, как у юнити в данный момент все плохо с переходом на DOTS.

Жду статью :)

Вообще с Burst не так все плохо, а вот с ECS беда. Там любое действие требует танцев с бубном

Хочу заметить, что "с ECS беда" конкретно в DOTS, сам по себе ECS как паттерн штука хорошая и в большинстве фреймворков не требует танцев с бубном, но юнитеки ради гипер-производительность очень переусложнили фреймворк

LeoEcs это прям супер пример, показывающий как надо делать ECS фреймворк. Особенно в сравнении с Entitas и ОСОБЕННО с UnityECS

Это да. После LeoECS количество годных ECS-фреймворков для шарпа начало увеличиваться: Actors, Morpeh, ME.ECS, DefaultECS... Такая тенденция не может не радовать.

Чтобы получить все преимущества Jobs и Burst, к счастью, необязательно использовать DOTS.

>>Могли сразу просто прямую поддержку плюсов впилить да и всё на этом.
Unity очень долго развивалась, а Burst появился не так давно. Менять сейчас c# на c++ не лучшая идея. Поэтому Burst это отличное решение.
Могли сразу просто прямую поддержку плюсов впилить да и всё на этом.

Так был же Managed C++. Правда, его достаточно быстро похоронили из-за его неэффективности.


В результате на выходе получится игра сравнимая по производительности с аналогом на c++.

Ну да. Вообще, даже JIT-компиляция в современном .NET не так уж и плоха (я даже замеры в задачах обработки изображений делал, сравнивая C# и C++ реализации — почти паритет). Тормоза C# — это миф, растущий корнями с .NET 1.0. Сейчас такого уже давно нет.

А сейчас в 6 ещё pgo завезут…

Сборка мусора. Да, есть incremental gc, но это не панацея, так как он дает лишь небольшой послабление, в любом случае необходимо все подряд пулить.

Ну можно не аллоципоывать на хипе и хрен с ним с GC:))

Можно, но сложно. Очень. Все самое вкусное — это managed типы, и, к примеру, массив из них на стеке через stackalloc/Span не разместить, если без unsafe.
По крайней мере, я попробовал, покрутил туда-сюда и плюнул на это дело.

Не, ну не совсем. Пока уровень грузится аллоцировал, а потом не аллоцируешь. В open world правда не прокатит

Всё это можно было написать гораздо короче )

В первом примере речь идёт о pattern matching. Хотя автор не видит ничего, кроме извращённой формы switch. PM появился в 60-х годах прошлого века. В дотнет он проложил путь 18 лет назад, когда вышел Nemerle. Наконец, его включили в C#. Да, да, дело не в узком кругозоре и непонимании контекста нововведения автором статьи, а авторы сишарпа не знают чем себя занять (нет). Кстати, зачем нужен PM и как он поможет писать более выразительный код — в принципе, можно было понять, просто 5 минут поглядев на пример, приведённый MS.

Во втором примере сначала var называют «уже достаточно спорным». Серьёзно?! Выведение типов, которое позволяет по выразительности подойти вплотную к динамической типизации, без которого руки начинают болеть через полчаса кодирования — спорное? Разумеется, нет. Но проблема с ним была в том, что не всюду выведение типов можно засунуть. В параметры функций — нельзя, в описание полей — нельзя. Но с параметрами функций ничего и не сделаешь (наверно), а вот в описании полей — очевиднейший копипаст, который так и напрашивается на сокращение. Его и сократили, только с другого конца. И правильно сделали — не описывать же поля с var'ом.

Итого: два примера, показывающих очень слабое понимание + набор неверных выводов из них. Больше ничего.

описании полей — очевиднейший копипаст, который так и напрашивается на сокращение. Его и сократили, только с другого конца. И правильно сделали — не описывать же поля с var'ом.

А почему бы и не описывать поля с var'ом? Что мешает в C# тип поля выводить? Вон в "дальнеродственном" Котлине - работает. Так не делают в С++ - но у них свои заморочки с типами вообще.

Как ни странно, я вчера как раз об этом же подумал. Может, потому, что сишарп — в первую очередь сишарп? ) И так-то недовольных полно, а тут совсем вонь поднимется до небес.

На самом деле, я очень люблю всё, что начинается на «си-», но со временем осознал, что есть свои преимущества в:

field Foo : int = 5;
field Bar = 5;
field Bas = new Hyper.Mega.SuperObject(42);

Компилируется только Котлин подольше

Смотрю со стороны с момента убийства Silverlight. Поэтому мало понимаю. Особенно в комментариях.

В исходной статье ссылка на тенденции Stack Overflow. Данные показывают однозначно - С# умирает. Смотрим на Go, Rust, Java, Kotlin, Dart, Flutter, Swift - выглядит правдоподобно. Значит, тенденции работают и то, что C# умирает - наблюдаемый факт. Если и спорить, то о том, продолжит ли умирать.

Как обстоит дело на самом деле, лучше всех знает Микрософт. Узнать что она знает не имея личной разведки и группировки спутников можно только по её действиям, а это .NET 6, который под пандемические оправдания опаздывает на один год, и MAUI, который на пол года минимум опаздывает ещё. Впечатление такое - полная (macOS, iPadOS, iOS, Android, Windows) кроссплатформенность считается условием выживания. MAUI опаздывает, Uno зато есть уже. Как можно говорить о будущем C# без неё - не понимаю, разве что фактическое наличие будущей кроссплатформенности, которая увы тенденции не ломает, может не нравиться.

Не только C# с .NET 6 и MAUI озаботилась кроссплатформенностью. Flutter сначала записал альфу и бету, macOS и Windows, в релиз, а потом прикрыл заднюю результатами опроса - мобилки и Интернет, дескать, людям важнее. Ну ладно, это для Микрософт Blazor - игрушка, а для Гугол Web - единственный источник дохода. Но тут и Go и Rust и Python и C++, у всех так или иначе полная кроссплатформенность уже есть. И Kotlin Native вроде как из беты выходит.

Почему все засуетились я думать не буду, а то ещё внесу запрещённую законом рознь упомянув Эппл. Но вопрос о том, всё ли хорошо будет у C#, вроде как сводится к двум. На сколько кроссплатформенность поможет и если поможет, то кому в первую очередь?

.Net 6 вроде бы production ready. Мы используем уже)

Вроде пока только release candidate. Т.е. пользоваться можно - но осторожно.

Не только C# с .NET 6 и MAUI озаботилась кроссплатформенностью

Не озаботилась. Поддержка Linux в MAUI не планируется в .NET 6.

Я так понимаю, что .NET 6 в каком-то виде на Линуксе будет, только MAUI приложений ни разрабатывать ни выполнять будет нельзя. Тогда в какой-то мере озаботилась, в какой-то нет. Как по мне, лучше так, чем, например, поддерживать Убунту и только Убунту.

.NET 6 в каком-то виде на Линуксе будет

.NET уже давно существует и прекрасно себя чувствует под Linux ещё со времён .NET Core, а до того момента была вполне себе полноценная реализация .NET Framework в виде Mono. Но вот кросс-платформенного GUI от Microsoft как не было, так и до сих пор нет.

В исходной статье ссылка на тенденции Stack Overflow. Данные показывают однозначно - С# умирает.

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

В принципе, может такое быть. Поэтому я и посмотрел остальное, а там результаты ожидаемые. Получается, что если JavaScript с его порогом, то действует он только на C# - тоже может в принципе так быть, но верится в последнюю очередь. Скорее если бы порог входа на что-то влиял, то в первую очередь убился бы Rust.

Согласен, что статья про очередную смерть C# не совсем корректна.

На данный момент гляжу на Unity и что творит Burst, это магия какая-то.

А .NET 6 с заявленной кросс-платформенностью выглядит очень интересно.

Я новичок. Новичок, который только начал свой путь разработчика. Пишу на работе по необходимости консольные утилиты на C#, скрипты на T-SQL.

Во-первых, дойдя до места, где в статье появляются ссылочки на курсы - я испытал откровенно негативные эмоции (т.к. потратил кучу времени на бесполезные курсы, где якобы за год из вас сделают fullstack - не сделают, проверил на себе). Во-вторых, статья вызывает грусть от ощущения, что очередной автор страдает синдромом утёнка...

Недавно я наткнулся на статью, где человек сравнивает доли языков бекенда при создании веб-сайтов. PHP, Ruby, Python...и туда же автор "анализов" запихнул фреймворк Asp.Net. Наверное многие, кто интересуется или разрабатывает на C#, видели эту статью. Там что-то около 78% доли PHP и слова о том, что Microsoft должна испугаться этих цифр....Почему? Мне не понятно.

Одни рекламируют свои курсы, пописывая всякий бред, другие сравнивают ЯПы с фреймворками, говоря об превосходстве конкретного ЯП на фреймворком... Хочу сказать им спасибо. Они из раза в раз все сильнее укрепляют моё желание самостоятельно изучать C#, со всеми его улучшениями, с Microsoft которая "убивает" язык, с 1.5% доли сайтов на Asp.Net...

Всё правильно делаете. "Собака лает, корован идëт" Смерть сишарпу горе-пророки предрекали ещё до выхода первой версии... Что касается сравнений с другими ЯП, то тут вообще клоунада: сравнивают по всей видимости те, кто не знает ни одного ЯП. Сейчас пишу на сишарп и джаве одновременно. С сишарпом имел опыт ещё в 2010-11 годах, потом был перерыв. Вернулся полгода назад. Вижу, что язык подрос и вполне себе живёт. Также и джава - многое туда перешло из котлина. Как идея, но как правило сделано это с оглядкой на прошлый опыт, а не просто "ну мы решили ещё и эту свистоперделку добавить". Это кстати одна из проблем новомодных (и не очень) языков - расширяем не что бы пользоваться, а потому что " это круто". За 20+ лет в ит я понял, что спешить некуда, идеи всë теже, только реализация с каждой итерацией лучше. И реально выходит, что нужно 5-7 итераций что бы продукт дорос до качества предшественника (разумеется исправив некоторые из его недостатков) Не много дорастает. Большая часть сваливается в забвение. Поэтому тут выбирать надо первым делом уже твёрдо стоящих на ногах. И сишарп, и джава, и плюсы безусловно к таким относятся. Остальным же ещё предстоит доказать, что они эту планку перешагнуть могут. А потому на них время нужно тратить по остаточному принципу. Ради интереса, хобби и т д. Но уж совсем глупо думать, что эти новички могут в одночасье "подсидеть" "титана".

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

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

А про какие тонкости Вы говорите? С моей точки зрения в C# стало даже меньше способов отстрелить себе ногу, по сравнению с 5 версией.

  1. Пофиксили проблемы с лямбдами в цикле

  2. Добавили полноценную иммутабельность, не нужно костыли писать

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

Из новых проблем я бы отметил только Tuples в коллекциях: они изменяемые структуры

На прошлой неделе наткнулся: рекорды поддержали в model binding, но Display(Name=***) в конструкторе забыли поддержать:) А так dto-шки рекордами - милое дело.

ушел когда появился первый .net core

Подскажите в текущем .net core webapi из коробки поддерживается DI для инициализации классов с дефолтным конструктором без мэппинга при старте приложения? (Ninject так работает)

Если я правильно понимаю, что вы хотите — да, поддерживается.


Но лучше приведите пример.

Sign up to leave a comment.

Articles