Por que "usar o Sistema"; não é considerado uma má prática?

47

Tenho experiência em C ++ e compreendo perfeitamente e concordo com as respostas a esta pergunta: Por que "usar o namespace std;" considerada má prática?

Então, estou surpreso que, tendo alguma experiência com C # agora, vejo exatamente o oposto: using Some.Namespace;é literalmente usado em todos os lugares. Sempre que você começa a usar um tipo, você adiciona uma diretiva using ao seu espaço para nome primeiro (se já não estiver lá). Não me lembro de ter visto um .csarquivo que não começou using System; using System.Collections.Generic; using X.Y.Z; etc.... De fato, se você adicionar um novo arquivo por meio do assistente do Visual Studio, ele adicionará automaticamente algumas diretivas de uso, mesmo que você não precise delas. Portanto, enquanto na comunidade C ++ você é basicamente linchado, o C # até incentiva isso. Pelo menos é assim que me parece.

Agora, eu entendo que o uso de diretivas em C # e C ++ não é exatamente a mesma coisa. Além disso, eu entendo que uma das coisas mais desagradáveis ​​que você pode fazer using namespaceem C ++, ou seja, colocá-lo em um arquivo de cabeçalho, não possui equivalente equivalente desagradável em C # devido à falta de um conceito de arquivos de cabeçalho e #include.

No entanto, apesar de suas diferenças, o uso de diretivas em C # e C ++ serve ao mesmo objetivo, que só precisa digitar SomeTypeo tempo todo, e não por muito mais tempo Some.Namespace.SomeType(em C ++ com em ::vez de .). E com esse mesmo objetivo, também o perigo parece ser o mesmo para mim: nomear colisões.

Na melhor das hipóteses, isso resulta em um erro de compilação, portanto você "apenas" precisa corrigi-lo. Na pior das hipóteses, ele ainda compila e o código silenciosamente faz coisas diferentes do que você pretendia. Então, minha pergunta é: Por que (aparentemente) estão usando diretivas consideradas tão desigualmente ruins em C # e C ++?

Algumas idéias de uma resposta que tenho (nenhuma delas realmente me satisfaz):

  • Os espaços para nome tendem a ser muito mais longos e muito mais aninhados em C # do que em C ++ ( stdvs. System.Collection.Generic). Portanto, há mais desejo e mais ganho em cancelar o código dessa maneira. Mas, mesmo que isso seja verdade, esse argumento só se aplica quando analisamos os espaços para nome padrão. Os personalizados podem ter qualquer nome abreviado que você queira, tanto em C # quanto em C ++.

  • Os espaços para nome parecem muito mais "finos granulares" em C # do que em C ++. Como exemplo, em C ++ toda a biblioteca padrão está contido em std(além de algumas pequenas namespaces aninhados gosto chrono) enquanto em C # você tem System.IO, System.Threading, System.Textetc. Assim, o risco de ter colisões de nomeação é menor. No entanto, este é apenas um pressentimento. Na verdade, não contei quantos nomes você "importa" com using namespace stde using System. E, novamente, mesmo que isso seja verdade, esse argumento se aplica apenas ao examinar os espaços para nome padrão. Seus próprios podem ser projetados com granularidade fina, conforme desejado, em C # e C ++.

Existem mais argumentos? Estou especialmente interessado em fatos concretos reais (se houver) e não tanto em opiniões.

sebrockm
fonte
2
@Timo O OP não está explicitamente perguntando sobre a poluição do cabeçalho.
Konrad Rudolph
11
Supus que fosse porque não há concorrência para o espaço de nomes global no mesmo grau que existe em C ++ (principalmente devido à biblioteca padrão C). Mas espero as respostas daqueles que sabem melhor.
Wyck
2
@ThomasWeller Em C ++ é óbvio. Em C #, considere um método de extensões com o Ext(this T t, long l)qual é chamado via t.Ext(0). Se você adicionar outro espaço para nome que contenha um método de extensão Ext(this T t, int i), esse será chamado. Mas eu não sou especialista em C # (ainda).
sebrockm 03/02
2
@ Frank, mesmo que eu tenha lhe dado esse ponto, o mesmo argumento se aplica ao C ++, empurrando ainda mais a minha questão de não ver a diferença entre C ++ e C #
sebrockm 03/02
3
O @Franck C ++ lançará um erro de compilação em você em caso de ambiguidade. Bem como c #.
Timo

Respostas:

28

Por que "usar o Sistema"; não é considerado uma má prática?

"using System;" é não universalmente não é considerado uma má prática. Veja, por exemplo: Por que você não usaria a diretiva 'using' em C #?

Mas pode ser verdade que não é considerado tão ruim quanto using namespace std. Provavelmente porque:

  1. C # não possui arquivos de cabeçalho. É incomum "incluir" um arquivo de origem C # em outro usando um pré-processador.

  2. stdO espaço para nome é quase plano, ou seja, quase todas as funções, tipos e variáveis ​​padrão da biblioteca estão nele (existem poucas exceções, como o sub-espaço para nome do sistema de arquivos). Ele contém um número muito, muito alto de identificadores. Na minha opinião, Systemcontém muito menos nomes e, em vez disso, possui mais sub-nomes de espaços.

  3. No C #, não há funções ou variáveis ​​globais. Como tal, o número de identificadores globais é tipicamente muito pequeno, em contraste com o C ++, que possui os seguintes: Além disso, é comum o uso de bibliotecas C (geralmente indiretamente) que não possuem espaços para nome e, portanto, colocam todos os seus nomes no global namespace.

  4. Até onde eu sei, o C # não tem pesquisa dependente de argumento. A ADL em conjunto com ocultação de nomes, sobrecarga, etc. pode produzir casos em que alguns programas não são afetados por um conflito de nomes, enquanto outros são sutilmente afetados, e a captura de todos os casos de canto não é viável com o teste.

Devido a essas diferenças, "using System;" tem menor chance de conflito de nome do que using namespace std.


Além disso, a "importação" de namespace é, de certa forma, uma convenção de autoperpetuação: se for convencional importar um namespace padrão, os programadores tentarão convencionalmente evitar escolher nomes desse namespace para seus próprios identificadores, o que ajuda a reduzir problemas com convenção.

Se essa importação for considerada uma prática ruim, é menos provável que os programadores tentem evitar esse conflito com os namespaces importados. Assim, as convenções tendem a polarizar-se a favor ou contra a prática, mesmo que os pesos dos argumentos entre as escolhas sejam originalmente sutis.

eerorika
fonte
3
Isso considera apenas possíveis desvantagens de abrir espaços para nome. Isso é um começo, mas acho que também precisamos considerar as vantagens: no caso do C ++, na maioria dos casos, ele economiza cinco caracteres ( std::). No C #, é substancialmente mais ( System.possui "apenas" 7 caracteres, mas outros namespaces aninhados têm muito mais caracteres, e escrevê-los em todos os lugares tornaria o código completamente ilegível).
Konrad Rudolph
Também não é o caso de a resolução de sobrecarga de C # ser mais gentil que a do C ++ e muita ambiguidade é extraída por meio de erros do compilador? (De maneira alguma uma crítica à sua resposta que parece autoritária.)
Bathsheba
3
@KonradRudolph Se os inconvenientes fossem considerados significativos e a quantidade de digitação igualmente (em comparação com a quantidade de digitação std::), não seria um estilo típico usar using Sys = System;o espaço de nomes que polui o não-alias using?
eerorika 03/02
2
@Bathsheba em relação a "autoritativo", gostaria de negar que sei muito pouco sobre C #, e minha resposta é baseada no conhecimento de C ++ e em algumas pesquisas no Google sobre C #. Então, eu apreciaria se alguém verificar as partes do C # :)
eerorika 03/02
2
Em relação à parte ADL: C # possui métodos de extensão. É um design diferente do ADL, mas eles compartilham os mesmos problemas em relação a conflitos de nomes.
Timo
-2

No entanto, apesar de suas diferenças, o uso de diretivas em C # e C ++ serve ao mesmo objetivo, que só precisa digitar SomeType o tempo todo, em vez de muito mais o Some.Namespace.SomeType (em C ++ com :: em vez de.). E com esse mesmo objetivo, também o perigo parece ser para mim: nomear colisões.

Sim, mas você não exportou esse perigo (leia-se: forçando outras pessoas a lidar com ele), devido a:

Agora, eu entendo que o uso de diretivas em C # e C ++ não é exatamente a mesma coisa. Além disso, eu entendo que uma das coisas mais desagradáveis ​​que você pode fazer com o uso de namespace em C ++, ou seja, colocá-lo em um arquivo de cabeçalho, não tem equivalente em C # devido à falta de um conceito de arquivos de cabeçalho e #include.

Portanto, é uma categoria diferente de coisa.

Além disso, o C ++ não é "projetado" para ser desenvolvido em um IDE da mesma forma que o C #. C # é basicamente sempre escrito no Visual Studio com seu Intellisense e outros enfeites. Ele foi projetado para ser usado dessa maneira pelas pessoas que o criaram. Independentemente de quantas pessoas usem um IDE para desenvolver em C ++, ele não foi projetado com esse caso de uso como uma preocupação esmagadora.

Os espaços para nome parecem muito mais "finos granulares" em C # do que em C ++.

Sim isso também. using namespace stde using System.Collection.Genericsão incomparáveis.

Portanto, não os compare!

Asteróides com asas
fonte
2
Isso não responde à preocupação do OP, que não é explicitamente abrir espaços para nome nos cabeçalhos, mas nos arquivos de implementação .
Konrad Rudolph
2
@KonradRudolph O conselho a evitar using namespace stdem C ++ é principalmente sobre arquivos de cabeçalho. A resposta é que isso não se aplica em C #.
Asteroids With Wings
8
@AsteroidsWithWings o conselho a evitar using namespace stdcertamente não é principalmente sobre cabeçalhos. Usá-lo em cabeçalhos é perigoso. É recomendável usá-lo em suas implementações.
Tommy Andersen
11
O conselho a evitar using namespace ...em c ++ é sobre como evitar colisões de nomes; a usingdiretiva em C # também introduz a possibilidade de nomear colisões; por que não evitá-las? Mesmo que haja implementação diferente.
Tommy Andersen
@ TommyAndersen, quão difícil é resolver esse conflito se isso acontecer? Demora um segundo. Como as usingdeclarações C # são por arquivo que define um tipo / classe único e o tipo normalmente tem a ver com um conjunto relativamente restrito de conceitos de domínio de aplicativo (idealmente, princípio de responsabilidade única), a probabilidade desses conflitos de namespace é extremamente baixa. Mas quando acontecem são facilmente corrigíveis. As ferramentas comuns de desenvolvimento .NET / IDE ajudam muito com isso. Considere todo o ecossistema de desenvolvimento projetado para torná-lo mais produtivo, combinando o melhor de várias atividades de desenvolvimento
AKornich