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.