Чому "використовується система;" не вважається поганою практикою?


47

У мене є C ++ фон, і я повністю розумію і погоджуюся з відповідями на це питання: Чому "використовується простір імен std;" вважається поганою практикою?

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

Тепер я розумію, що використання директив у C # та C ++ - це не те саме. Крім того, я розумію, що одна з найнебезпечніших речей, яку ви можете зробити using namespaceв C ++, а саме, поміщаючи її в заголовок, не має еквівалентно неприємного аналога в C # через відсутність концепції файлів заголовків і #include.

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

У кращому випадку це призводить до помилки компіляції, тож вам доведеться виправити "лише". У гіршому випадку він все-таки компілюється, і код мовчки робить інші речі, ніж ви цього мали намір зробити. Отже, моє запитання: чому (мабуть) використовуються директиви, які вважаються такими нерівно поганими в C # і C ++?

Деякі ідеї відповіді, яку я маю (хоча жодна з цих дійсно мене не задовольняє):

  • Простори імен, як правило, значно довші та значно більше вкладених у C #, ніж у C ++ ( stdпорівняно System.Collection.Generic). Таким чином, є більше бажання і більше вигоди в знеструмленні коду таким чином. Але навіть якщо це правда, цей аргумент застосовується лише тоді, коли ми дивимось на стандартні простори імен. Користувацькі можуть мати будь-яке коротке ім’я, як у C #, так і в C ++.

  • Простори імен здаються набагато більш "дрібнозернистими" в C #, ніж у C ++. В якості прикладу, в C ++ вся стандартна бібліотека міститься в std(плюс деякі крихітні вкладені простору імен подобається chrono) , а в C # у вас є System.IO, System.Threading, і System.Textт.д. Таким чином, ризик виникнення конфліктів імен менше. Однак це лише відчуття кишки. Я насправді не підраховував, скільки імен ви "імпортуєте" using namespace stdі using System. І знову, навіть якщо це правда, цей аргумент застосовується лише при перегляді стандартних просторів імен. Ваші власні можуть бути сконструйовані настільки дрібнозернистими, як ви хочете, як на C #, так і на C ++.

Чи є більше аргументів? Мене особливо цікавлять фактичні важкі факти (якщо такі є) і не так багато думок.


2
@Timo OP явно не запитує про забруднення заголовка.
Конрад Рудольф

1
Я припускав, що це не є конкуренція за глобальний простір імен в тій же мірі, що і в C ++ (в першу чергу завдяки стандартній бібліотеці С). Але я чекаю відповідей тих, хто найкраще знає.
Вік

2
@ThomasWeller У C ++ це очевидно. У C # розглянемо метод розширення, Ext(this T t, long l)який називається via t.Ext(0). Якщо ви додасте інше простір імен, що містить метод розширення Ext(this T t, int i), він буде викликаний замість цього. Але я не є експертом у C # (поки що).
sebrockm

2
@Franck, навіть якщо я надав вам цю точку, то той самий аргумент стосується і C ++, що ще більше підштовхує моє запитання про те, щоб не бачити різниці між C ++ та C #
sebrockm

3
@Franck C ++ викине на вас помилку компілятора у разі неоднозначності. А також C #.
Тимо

Відповіді:


28

Чому "використовується система;" не вважається поганою практикою?

"за допомогою системи;" це НЕ універсально не рахується поганою практикою. Дивіться наприклад: Чому б ви не використовували директиву "using" в C #?

Але це може бути вірно , що це не вважається зовсім не сподобалася , як using namespace std. Можливо, тому що:

  1. У C # немає файлів заголовків. Нечасто "включати" один вихідний файл C # в інший за допомогою попереднього процесора.

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

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

  4. Наскільки я знаю, C # не має аргументованого пошуку. ADL у поєднанні з приховуванням імен, перевантаження і т. Д. Може спричинити випадки, коли на деякі програми не впливає конфлікт імен, а на інші - це чітко позначається, і випробування всіх кутових випадків неможливо перевірити.

Через ці відмінності "використання системи;" має менший шанс конфлікту імен, ніж using namespace std.


Крім того, імпортування простору імен - це певна умова, що постійно веде себе: Якщо імпортувати стандартний простір імен, звичайно, програмісти намагаються уникати вибору імен з цього простору імен для власних ідентифікаторів, що допомагає зменшити проблеми з така конвенція.

Якщо такий імпорт вважається поганою практикою, програмісти будуть менше спробувати навіть уникнути конфліктів із імпортованими просторами імен. Таким чином, конвенції мають тенденцію до поляризації для або проти практики, навіть якщо ваги аргументів між виборами спочатку були тонкими.


3
Це враховує лише потенційні недоліки відкриття просторів імен. Це початок, але я думаю, що ми також повинні враховувати переваги: ​​у випадку C ++, у більшості випадків, це економія п'яти символів ( std::). У C # - це значно більше ( System.має "лише" 7 символів, але в інших вкладених просторах імен є набагато більше символів, і записування їх скрізь зробить код абсолютно нечитабельним).
Конрад Рудольф

Чи не так також, що роздільна здатність перевантаження C # є добрішою, ніж у C ++, і багато неоднозначності виводиться через помилки компілятора? (У жодному разі не критику вашої відповіді, яка здається авторитетною.)
Вірсавія

3
@KonradRudolph Якщо недоліки вважалися б істотними, а кількість набраних однаковою мірою (порівняно з кількістю набору тексту std::), не було б типовим стилем використовувати using Sys = System;замість простору імен, що забруднюють не псевдоніми using?
eerorika

2
@Bathsheba щодо "авторитетного", я хочу заперечувати, що я дуже мало знаю про C #, і моя відповідь ґрунтується на знаннях C ++ та кількох пошукових запитах Google про C #. Отже, я вдячний, якщо хтось факт перевірить C # частини :)
eerorika

2
Щодо частини ADL: C # має методи розширення. Це інший дизайн, ніж ADL, але вони мають ті ж проблеми, що стосуються іменних конфліктів.
Тимо

-2

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

Так, але ви не експортували цю небезпеку (читайте: змушуючи інших боротися з нею) через:

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

Тож це зовсім інша категорія речей.

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

Простори імен здаються набагато більш "дрібнозернистими" в C #, ніж у C ++.

Так, це теж. using namespace stdі using System.Collection.Genericнезрівнянні.

Тому не порівнюйте їх!


2
Це не відповідає занепокоєнню ОП, що явно не про відкриття просторів імен у заголовках, а у файлах реалізації .
Конрад Рудольф

2
@KonradRudolph Порада, яку слід уникати using namespace stdв C ++, здебільшого стосується файлів заголовків. Відповідь полягає в тому, що це не стосується C #.
Астероїди з крилами

8
@AsteroidsWithWings поради, яких уникати using namespace std, звичайно, не стосуються переважно заголовків. Використовувати його в заголовках небезпечно. Використовувати його у своїх реалізаціях не рекомендується.
Томмі Андерсен

1
Порада, яку слід уникати using namespace ...в c ++, стосується уникнення зіткнення імен, usingдиректива в C # також вводить можливість зіткнення імен, а чому б цього не уникнути? Незважаючи на те, що там реалізація відрізняється.
Томмі Андерсен

@TommyAndersen, наскільки складно вирішити такий конфлікт, якщо він трапився? Це займає секунду. Оскільки usingдекларації C # поширюються на файл, який визначає тип одного класу / класу, а тип зазвичай має відношення до відносно вузького набору понять доменних додатків (в ідеалі - принципу єдиної відповідальності), ймовірність таких зіткнень у просторі імен надзвичайно низька. Але коли трапляються, це легко виправити. Загальні засоби розробки .NET / IDE дуже допомагають вам у цьому. Розглянемо всю екосистему розвитку, яка покликана зробити вас більш продуктивними, поєднуючи найкращі з декількох видів розвитку
AKornich
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.