Выбор между C++ и C#

MR_smoker

Арбитр
АРБИТРАЖ
ПРОВЕРЕННЫЙ ПРОДАВЕЦ
ЮБИЛЕЙНАЯ ЛЕНТА

MR_smoker

Арбитр
АРБИТРАЖ
ПРОВЕРЕННЫЙ ПРОДАВЕЦ
ЮБИЛЕЙНАЯ ЛЕНТА
Регистрация
20 Июн 2018
Сообщения
1,734
Реакции
632
Репутация
39
Род занятий

Отрисовка документов

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

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

Отдельных статей требует рассмотрение выбора Java или же интерпретируемых языков. Они будут предпочтительнее, чем С++ или С# в некоторых случаях, однако вынесем такие случаи за рамки данной статьи и сфокусируемся на сравнении С++ и С#.

Для ясности обозначу, что под C++ буду понимать unmanaged код, а под C# — managed код. В статье можно было сравнить managed и unmanaged, но это было бы менее полезно практический. А mixed код, хотя он и представляет некоторый интерес, оставим по большей части за рамками данной статьи.

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

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

2. Кросплатформенность

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

C# спроектирован быть кросплатформенным, однако его развитие не пошло в этом направлении. Поэтому под Windows образовалась достаточно полная .net инфраструктура; на других же платформах равноценной инфраструктуры не появилось.

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

И хотя С# возможно использовать для построения приложений под не-Windows платформы, проблемы, вызываемые использованием .net в не-Windows окружении, сводят на нет многие преимущества выбора C#. Поэтому рекомендовать его для кроссплатформенного использования можно разве что если код на C# уже написан. При этом надо четко понимать, что в перспективе это будет приносить дополнительные затраты на поддержку.

3. Производительность кода и требовательность к ресурсам

Очевидным является факт того, что возможности по оптимизации unmanaged кода куда шире, чем возможности по оптимизации managed кода. Таким образом, пиковая производительность кода достижима только в unmanaged исполнении, т.е. в пределе, почти любая задача на С++ может быть решена с меньшими требованиями к ресурсам. Поэтому в тяжелых задачах, связанных с обработкой большого количества данных, С++ имеет сильные преимущества перед С#.

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

Если говорить о совокупности субъективных «простоты разработки», «красоты кода» и объективной производительности, то используя C# проще написать код, удовлетворяющий этим критериям одновременно. Однако это не значит, что производительный код на С++ обязательно будет страшным или сложным для восприятия, просто при его написании потребуется более «творческий» подход для удовлетворения перечисленных критериев одновременно.

Фундаментальные основы преимуществ С++ в возможности писать код, который будет выполняться непосредственно процессором, и возможности прямой работы с памятью. Конечно, свобода дает больше возможностей создать себе проблемы, но в ряде случаев это лучше, чем невозможность преодоления потолка производительности. И этот потолок вполне может привести, например, к тому, что под решение задачи, для которого бы хватило одного хорошего сервера, вам придется собирать ферму из нескольких серверов, или же к тому, что ваше приложение будет требовать «топового» железа на задачи, для которых хватило бы железа выпущенного лет 7-10 назад.

4. Библиотеки

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

Другая неприятная особенность С++ библиотек — это создание и переопределение своих базовых типов. Многие С++ библиотеки заводят свои типы строк, контейнеров, переопределяют некоторые базовые типы. Этому есть логичные объяснения (лучшая производительность, поддержка кросплатформенности, отсутствие подходящих типов на момент написание библиотеки), однако все это не добавляет удобства использования и красоты коду. Базовые же С++ библиотеки дают не так много, как дают стандартные библиотеки С#, поэтому подбор правильных библиотек для проекта С++ — это задача, необходимая даже в сравнительно простых проектах.

Однако не все так страшно, для С++ есть немало и «красивых» библиотек. Да и базовые библиотеки постоянно расширяются. Вопрос часто лишь в том, каких жертв потребует данная красота.

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

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

Вторая неприятная особенность библиотек С# в том, что многие из них являются просто оберткой над unmanaged библиотеками, что будет всегда приводить к потерям производительности на конверсиях типов, и создавать дополнительные проблемы отладки и распространения.

5. Удобство отладки

Можно было бы просто сказать, что под Window, С# заметно удобнее отлаживать и на этом остановиться.
Однако если по какой-то причине у вас на ряду с mananged кодом из C# сборки используется unmanаged, то его отладка будет станет более сложная по сравнению с обычной отладкой unmamanged кода из С++.

6. Язык и Синтаксис

С первого взгляда код С++ и С# очень похож внешне. Но многообразие кода на С++ больше, ведь С++ является одновременно и С и С++ и С++0х и все это вы можете использовать одновременно (конечно, если это поддерживает ваш компилятор).

С# же, это только C#, хотя его синтаксис постоянно расширяется. Код на С#, как правило, выглядит проще и лаконичнее, чем код С++ (хотя это не всегда можно было сказать про первые версии С#). Языковые конструкции С++ и С# очень схожи, однако существенные различия можно найти в деталях.
Если С++ можно упрекнуть за отсутствие «в базе» reflection, позднего связывания и сборки мусора. То С# надо упрекнуть за отсутствие полноценных деструкторов, отсутствие полноценных макросов, достаточно грубую настройку наследования, отсутствие константных методов и членов, отсутствие глобальным методов (процедур), очень ограниченную поддержку шаблонов, список можно продолжать… Однако жить без всего этого вполне можно как в случае С++, так и в случае C#.

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

Стоит сказать, что более сложный код часто легче пишется и анализируется, если написан более простым языком. С этой позиции, используя С#, меньше шансов допустить ошибку в принципиально сложном коде и больше шансов написать чистый код, обладая теми же ресурсами. Это может быть полезно при решении достаточно сложных, но не требовательных к производительности задач. Однако при этом большее количество «синтетики» в С# делает меньше оценку производительности кода по его «внешнему виду».

7. Стоимость поддержки

В поддержке приложений большой разницы между С++ и С# нет. Хотя стоит понимать, что некоторые баги в приложениях, написанных на C#, средствами .net исправить невозможно и при необходимости их исправить стоимость поддержки может существенно возрасти. Однако если говорить о рефакторинге, то зачастую приложения, написанные на C#, рефакторить несколько дешевле.

8. Риски

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

Риски использования С++ тоже есть, но это другие риски. Основным я бы назвал проблемы, связанные с бинарной совместимостью библиотек. Если ваши библиотеки не в исходниках, то вам важно чтобы они были совместимы. Например, переход на другой runtime будет возможен только при перестроении или получении новых версий библиотек, работа же нескольких runtime-ов в одном процессе может приводить к проблемам взаимодействия. Все это может существенно удорожить развитие проекта.

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

В случае С++ ситуация с низкокачественных кодом несколько лучше, т.к. шансы на выживание у плохого кода ниже, однако панацеей от плохого кода С++ конечно не является.

9. Самодостаточность приложений

Полной самодостаточности приложений нет ни у C++ ни у С#. Для С++ так или иначе нужен runtime, а для C# .net framework.
Однако хотелось бы отметить, что рантайм С++, как и любая другая библиотека, может быть статический линкован в исполняемый модуль, таким образом исполняемый модуль может содержать все необходимое для работы, и за счет чего станет самодостаточным, в случае С# такое, стандартными средствами не реализуемо.

10. Удобство сборки

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

11. Перспективы

Рассуждения о перспективах это всегда спекуляция. На сегодня и С++ и C# активно развиваются (хотя С++ начал активно развиваться не так давно) Однако что будет дальше?

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

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

Выводы

Не могу сказать, что есть универсальный ответ на вопрос «С++ или же С# использовать для очередного проекта?», однако же могу сказать, что в разные периоды своей деятельность я бы по разному отвечал на вопрос о выборе, и если лет 5 назад я бы не рассматривал C++ как предпочтительный выбор, то сейчас в большем количестве случаев склонюсь к тому, чтобы использовать его. Однако, думаю, что для быстрого прототипирования под Windows C# является и, возможно, будет являться предпочтительным решением относительно С++.
 
Сверху