У меня есть опыт работы с 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++.
Есть ли еще аргументы? Меня особенно интересуют реальные факты (если они есть), а не столько мнения.
Почему "использование System;" не считается плохой практикой?
"Использование System;" не повсеместно не считается плохой практикой. См. например: Почему вы не должны использовать директиву 'using' в C#?
Но, возможно, это правда, что она не считается настолько плохой, как использование пространства имен std
. Возможно, потому что:
В C# нет заголовочных файлов. Очень редко можно "включить" один исходный файл C# в другой с помощью препроцессора.
Пространство имен std
почти плоское, т.е. почти все функции, типы и переменные стандартной библиотеки находятся в нем (есть несколько исключений, например, подпространство имен файловой системы). Оно содержит очень, очень большое количество идентификаторов. Насколько я понимаю, System
содержит гораздо меньше имен, а вместо этого имеет больше подпространств имен.
В C# нет глобальных функций или переменных. Поэтому количество глобальных идентификаторов обычно довольно мало, в отличие от C++, где они есть: Кроме того, типичным является использование библиотек C (часто косвенно), которые не имеют пространств имен и поэтому помещают все свои имена в глобальное пространство имен.
Насколько я знаю, в C# нет аргументозависимого поиска. ADL в сочетании с сокрытием имен, перегрузкой и т.д. может привести к ситуациям, когда на некоторые программы конфликт имен не повлияет, а на другие повлияет едва заметно, и отловить все угловые случаи не представляется возможным при тестировании.
Из-за этих различий "using System;" имеет меньшую вероятность конфликта имен, чем using namespace std
.
Кроме того, пространство имен "импортирование" в некотором смысле является самоподдерживающейся конвенцией: Если принято импортировать стандартное пространство имен, то программисты будут условно стараться избегать выбора имен из этого пространства имен для своих собственных идентификаторов, что помогает уменьшить проблемы с таким соглашением.
Если такой импорт считается плохой практикой, то программисты будут менее склонны даже пытаться избегать конфликтов с импортированными пространствами имен. Таким образом, конвенции становятся поляризованными в пользу или против такой практики, даже если весомость аргументов между этими вариантами изначально была незначительной.
Однако, несмотря на различия, использование директив в 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 несравнимы.
Так что не сравнивайте их!