Почему "использование системы" не считается плохой практикой?

У меня есть опыт работы с C++, и я полностью понимаю и согласен с ответами на этот вопрос: Почему "using namespace std;" считается плохой практикой?

Поэтому я поражен тем, что, имея некоторый опыт работы с C#, я вижу там прямо противоположное: using Some.Namespace; используется буквально везде. Всякий раз, когда вы начинаете использовать тип, вы сначала добавляете директиву using для его пространства имен (если его там еще нет). Я не могу вспомнить, чтобы я видел .cs-файл, который не начинался бы с using System; using System.Collections.Generic; using X.Y.Z; etc.... Фактически, если вы добавляете новый файл с помощью мастера Visual Studio, он автоматически добавляет туда несколько директив using, хотя они могут и не понадобиться. Таким образом, в то время как в сообществе C++ вас практически линчуют, C# даже поощряет это. По крайней мере, так мне кажется.

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

Однако, несмотря на различия, использование директив в C# и C++ служит одной и той же цели, которая заключается в необходимости постоянно вводить SomeType, а не гораздо более длинное Some.Namespace.SomeType (в C++ с :: вместо .). И с этой же целью, опасность, как мне кажется, та же: столкновения имен.

В лучшем случае это приводит к ошибке компиляции, так что вам "всего лишь" придется ее исправить. В худшем случае, он все равно компилируется, а код молча делает не то, что вы задумали. Поэтому мой вопрос таков: **Почему (по всей видимости) использование директив считается одинаково плохим в C# и C++?

Некоторые идеи ответа, которые у меня есть (хотя ни одна из них меня не удовлетворяет):

  • Пространства имен в C# гораздо длиннее и гораздо более вложенные, чем в C++ (std против System.Collection.Generic). Таким образом, есть больше желания и больше выгоды в де-noise кода таким образом. Но даже если это правда, этот аргумент применим только при рассмотрении стандартных пространств имен. Пользовательские могут иметь любое короткое имя, которое вам нравится, как в C#, так и в C++.

  • Пространства имен кажутся гораздо более "мелкозернистыми" в C#, чем в C++. Например, в C++ вся стандартная библиотека содержится в std (плюс несколько крошечных вложенных пространств имен, таких как chrono), в то время как в C# есть System.IO, System.Threading, System.Text и т.д. Таким образом, риск столкновения имен меньше. Однако, это всего лишь интуитивное ощущение. Я не считал, сколько имен вы "импортируете" с использованием пространства имен std и использованием System. И опять же, даже если это правда, этот аргумент применим только при рассмотрении стандартных пространств имен. Ваши собственные могут быть разработаны настолько мелкозернисто, насколько вы пожелаете, как в C#, так и в C++.

Есть ли еще аргументы? Меня особенно интересуют реальные факты (если они есть), а не столько мнения.

Комментарии к вопросу (31)
Решение

Почему "использование System;" не считается плохой практикой?

"Использование System;" не повсеместно не считается плохой практикой. См. например: Почему вы не должны использовать директиву 'using' в C#?

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

  1. В C# нет заголовочных файлов. Очень редко можно "включить" один исходный файл C# в другой с помощью препроцессора.

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

  3. В C# нет глобальных функций или переменных. Поэтому количество глобальных идентификаторов обычно довольно мало, в отличие от C++, где они есть: Кроме того, типичным является использование библиотек C (часто косвенно), которые не имеют пространств имен и поэтому помещают все свои имена в глобальное пространство имен.

  4. Насколько я знаю, в C# нет аргументозависимого поиска. ADL в сочетании с сокрытием имен, перегрузкой и т.д. может привести к ситуациям, когда на некоторые программы конфликт имен не повлияет, а на другие повлияет едва заметно, и отловить все угловые случаи не представляется возможным при тестировании.

Из-за этих различий "using System;" имеет меньшую вероятность конфликта имен, чем using namespace std.


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

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

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

Однако, несмотря на различия, использование директив в C# и C++ служит одной и той же цели, которая заключается в необходимости постоянно вводить SomeType, а не гораздо более длинный Some.Namespace.SomeType (в C++ с :: вместо .). И с этой же целью возникает опасность: столкновения имен.

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

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

Так что это скорее другая категория вещей.

Кроме того, C++ не "предназначен" для разработки в IDE так же, как C#. C# в основном всегда пишется в Visual Studio с ее Intellisense и прочим. Он предназначен для использования таким образом людьми, которые его создали. Независимо от того, сколько людей используют IDE для разработки на C++, она не предназначена для такого использования.

Пространства имен кажутся гораздо более "мелкозернистыми" в C#, чем в C++.

Да, и это тоже. Использование пространства имен std и использование System.Collection.Generic несравнимы.

Так что не сравнивайте их!

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