Perché "utilizza il sistema;" non considerato cattiva pratica?


47

Ho un background C ++ e capisco perfettamente e sono d'accordo con le risposte a questa domanda: Perché "usare lo spazio dei nomi std;" considerata cattiva pratica?

Quindi sono stupito che, avendo una certa esperienza con C # ora, vedo esattamente l'opposto lì: using Some.Namespace;viene letteralmente usato ovunque. Ogni volta che inizi a utilizzare un tipo, aggiungi prima una direttiva using per il suo spazio dei nomi (se non è già presente). Non ricordo di aver visto un .csfile che non era iniziato using System; using System.Collections.Generic; using X.Y.Z; etc.... In effetti, se aggiungi un nuovo file tramite la procedura guidata di Visual Studio, ne aggiunge automaticamente alcune usando le direttive lì, anche se potresti non averne affatto bisogno. Quindi, mentre nella comunità C ++ vieni sostanzialmente linciato, C # incoraggia persino a farlo. Almeno è così che mi appare.

Ora capisco che usare le direttive in C # e C ++ non è esattamente la stessa cosa. Inoltre, capisco che una delle cose più cattive che puoi fare using namespacein C ++, vale a dire metterlo in un file di intestazione, non ha una controparte equivalentemente cattiva in C # a causa della mancanza di un concetto di file di intestazione e #include.

Tuttavia, nonostante le loro differenze, l'uso delle direttive in C # e C ++ ha lo stesso scopo, che deve solo digitare SomeTypetutto il tempo, piuttosto che molto più Some.Namespace.SomeTypea lungo (in C ++ con ::invece di .). E con questo stesso scopo, anche il pericolo sembra essere lo stesso per me: nominare le collisioni.

Nel migliore dei casi questo si traduce in un errore di compilazione, quindi "solo" devi risolverlo. Nel peggiore dei casi, si compila ancora e il codice fa silenziosamente cose diverse da quelle che tu intendevi fare. Quindi la mia domanda è: perché (apparentemente) stanno usando le direttive considerate in modo così diseguale in C # e C ++?

Alcune idee di una risposta che ho (nessuna di queste mi soddisfa davvero):

  • Gli spazi dei nomi tendono ad essere molto più lunghi e molto più nidificati in C # che in C ++ ( stdvs. System.Collection.Generic). Quindi, c'è più desiderio e più guadagno nel de-rumorizzare il codice in questo modo. Ma anche se questo è vero, questo argomento si applica solo quando guardiamo gli spazi dei nomi standard. Quelli personalizzati possono avere qualsiasi nome breve che ti piace, sia in C # che in C ++.

  • Gli spazi dei nomi sembrano essere molto più "fini" in C # che in C ++. A titolo di esempio, in C ++ l'intera libreria standard è contenuta in std(oltre ad alcuni piccoli spazi dei nomi nidificati piace chrono), mentre in C # si dispone System.IO, System.Threading, System.Textecc Quindi, il rischio di avere conflitti di denominazione è più piccolo. Tuttavia, questa è solo una sensazione viscerale. In realtà non ho contato quanti nomi "importate" con using namespace stde using System. E ancora, anche se questo è vero, questo argomento si applica solo quando si osservano gli spazi dei nomi standard. I tuoi possono essere progettati come granulare come desideri, sia in C # che in C ++.

Ci sono più argomenti? Sono particolarmente interessato ai fatti concreti reali (se ce ne sono) e non tanto alle opinioni.


2
@Timo L'OP non chiede esplicitamente l' inquinamento delle intestazioni.
— Konrad Rudolph,

1
Ho pensato che fosse perché non c'è competizione per lo spazio dei nomi globale nella stessa misura in C ++ (principalmente a causa della libreria standard C). Ma aspetto le risposte di chi conosce meglio.
— Wyck,

2
@ThomasWeller In C ++ è ovvio. In C # considera un metodo di estensione Ext(this T t, long l)che viene chiamato via t.Ext(0). Se quindi aggiungi un altro spazio dei nomi che contiene un metodo di estensione Ext(this T t, int i), verrà invece chiamato quello. Ma non sono un esperto di C # (ancora).
— sebrockm,

2
@Franck anche se ti ho concesso questo punto, lo stesso argomento si applica al C ++, spingendo ulteriormente la mia domanda di non vedere la differenza tra C ++ e C #
— sebrockm

3
@Franck C ++ genererà un errore del compilatore in caso di ambiguità. Così come C #.
— Timo

Risposte:


28

Perché "utilizza il sistema;" non considerato cattiva pratica?

"utilizzo del sistema;" non è universalmente considerato una cattiva pratica. Vedi ad esempio: Perché non dovresti usare la direttiva "using" in C #?

Ma può essere vero che non è considerato così male come using namespace std. Probabilmente perché:

  1. C # non ha file di intestazione. È raro "includere" un file sorgente C # in un altro usando un pre-processore.

  2. stdlo spazio dei nomi è quasi piatto, ovvero quasi tutte le funzioni standard della libreria, i tipi e le variabili sono presenti (ci sono poche eccezioni come lo spazio dei nomi dei filesystem). Contiene un numero molto, molto elevato di identificatori. A mio avviso, Systemcontiene molti meno nomi e ha invece più spazi dei nomi secondari.

  3. In C # non ci sono funzioni o variabili globali. Come tale, il numero di identificatori globali è in genere piuttosto piccolo in contrasto con C ++ che ha quelli: Inoltre, è tipico usare librerie C (spesso indirettamente) che non hanno spazi dei nomi, e quindi posizionare tutti i loro nomi nel globale namespace.

  4. Per quanto ne so, C # non ha una ricerca dipendente dall'argomento. L'ADL in combinazione con nascondere i nomi, sovraccaricare ecc. Può produrre casi in cui alcuni programmi non sono interessati da un conflitto di nomi, mentre altri sono sottilmente interessati e non è possibile catturare tutti i casi angolari con i test.

A causa di queste differenze, "using System;" ha meno possibilità di conflitto di nomi rispetto a using namespace std.


Inoltre, namespace "importazione" è in un certo senso, una convenzione autoalimenta: Se è convenzionale per importare uno spazio dei nomi standard, allora programmatori convenzionalmente cercano di evitare di scegliere i nomi da quello spazio dei nomi per i propri identificatori, che aiuta a ridurre i problemi con tale convenzione.

Se tale importazione è considerata una cattiva pratica, i programmatori avranno meno probabilità di tentare persino di evitare tali conflitti con gli spazi dei nomi importati. Pertanto, le convenzioni tendono a polarizzarsi a favore o contro la pratica, anche se in origine i pesi degli argomenti tra le scelte erano sottili.


3
Ciò considera solo i potenziali svantaggi dell'apertura di spazi dei nomi. Questo è un inizio, ma penso che dobbiamo anche considerare i vantaggi: nel caso del C ++, nella maggior parte dei casi sta salvando cinque caratteri ( std::). In C #, è sostanzialmente più ( System.ha "solo" 7 caratteri, ma altri spazi dei nomi nidificati hanno molti più caratteri, e scriverli ovunque renderebbe il codice completamente illeggibile).
— Konrad Rudolph,

Non è anche il caso che la risoluzione del sovraccarico in C # sia più gentile di quella in C ++ e che molta errore sia compilato attraverso errori del compilatore? (Non è affatto una critica alla tua risposta che sembra autorevole.)
— Bathsheba

3
@KonradRudolph Se gli svantaggi fossero considerati significativi, e la quantità di battitura allo stesso modo (rispetto alla quantità di battitura std::), non sarebbe lo stile tipico usare using Sys = System;invece lo spazio dei nomi che inquina non alias using?
— eerorika,

2
@Bathsheba per quanto riguarda "autorevole", vorrei negare che so molto poco di C # e la mia risposta si basa sulla conoscenza di C ++ e alcune ricerche su Google su C #. Quindi, apprezzerei se qualcuno effettivamente controlla le parti C # :)
— eerorika,

2
Per quanto riguarda la parte ADL: C # ha metodi di estensione. È un design diverso da ADL, ma condividono gli stessi problemi relativi ai conflitti di denominazione.
— Timo,

-2

Tuttavia, nonostante le loro differenze, l'uso delle direttive in C # e C ++ ha lo stesso scopo, che deve solo digitare SomeType per tutto il tempo, piuttosto che il molto più lungo Some.Namespace.SomeType (in C ++ con :: anziché.). E con questo stesso scopo, sembra esserci anche il pericolo: nominare le collisioni.

Sì, ma non hai esportato quel pericolo (leggi: costringere gli altri a gestirlo), a causa di:

Ora capisco che usare le direttive in C # e C ++ non è esattamente la stessa cosa. Inoltre, capisco che una delle cose più brutte che puoi fare con l'uso dello spazio dei nomi in C ++, vale a dire metterlo in un file di intestazione, non ha equivalenti in C # a causa della mancanza di un concetto di file di intestazione e #include.

Quindi è piuttosto una categoria diversa di cose.

Inoltre, C ++ non è "progettato" per essere sviluppato in un IDE allo stesso modo di C #. C # è praticamente sempre scritto in Visual Studio con il suo Intellisense e quant'altro. È progettato per essere utilizzato in questo modo, dalle persone che lo hanno creato. Indipendentemente da quante persone usano un IDE per sviluppare in C ++, non è progettato con quel caso d'uso come una preoccupazione travolgente.

Gli spazi dei nomi sembrano essere molto più "fini" in C # che in C ++.

Sì, anche quello. using namespace stde using System.Collection.Genericsono incomparabili.

Quindi non confrontarli!


2
Ciò non risponde alla preoccupazione di OP, che non riguarda esplicitamente l' apertura di spazi dei nomi nelle intestazioni, ma nei file di implementazione .
— Konrad Rudolph,

2
@KonradRudolph I consigli da evitare using namespace stdin C ++ riguardano principalmente i file header. La risposta è che ciò non si applica in C #.
— Asteroidi con ali

8
@AsteroidsWithWings i consigli da evitare using namespace stdnon riguardano certo le intestazioni. Usarlo nelle intestazioni è pericoloso. L'uso è sconsigliato nelle implementazioni.
— Tommy Andersen,

1
Il consiglio da evitare using namespace ...in c ++ è di evitare la collisione dei nomi, la usingdirettiva in C # introduce anche la possibilità di nominare la collisione, quindi perché non evitarlo? Anche se l'implementazione differisce.
— Tommy Andersen,

@ TommyAndersen, quanto è difficile risolvere un simile conflitto se succede? Ci vuole un secondo Poiché le usingdichiarazioni C # sono per file che definiscono un singolo tipo / classe e il tipo normalmente ha a che fare con un insieme relativamente ristretto di concetti del dominio dell'applicazione (idealmente, principio di responsabilità singola) la probabilità di tali scontri nello spazio dei nomi è estremamente bassa. Ma quando succede sono facilmente riparabili. Strumenti di sviluppo .NET / IDE comuni ti aiutano molto in questo. Considera l'intero ecosistema di sviluppo progettato per renderti più produttivo combinando il meglio delle molteplici attività di sviluppo
— AKornich
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.