Como funciona namespaces no C#?
Funções
Namespaces são confundidos por muitos programadores. Há dois entendimentos úteis.
Primeiro para organizar seus tipos logicamente. É como se você colocasse determinados tipos (classes, estruturas, enumerações, delegações, interfaces, etc.) que são relacionados de alguma forma em uma mesma "caixa". A sintaxe da linguagem dá bem a indicação que é isto que ocorre. Mas é enganosa.
O segundo entendimento é desambiguar nomes de tipos que parecem ser conflitantes. Ou seja, você pode ter dois ou mais tipos com o mesmo nome na sua aplicação (dentro do seu projeto ou externamente), desde que eles estejam em namespaces diferentes.
Ele não encapsula nada
Este entendimento mostra que apesar da visão que os programadores têm sobre o namespace ser um módulo, uma caixa de tipos (como indica a primeira função), na realidade ele funciona como um sobrenome para para os tipos. Um sobrenome funciona como uma forma de nomear uma família. Assim você pode ter dois Ricardo
s no mesmo ambiente sem confusão, porque um é Oliveira
e o outro é Silva
.
Então quando você cria:
namespace Estoque {
public class FormCadastro { ... }
}
Na verdade internamente é criado:
public class Estoque.FormCadastro { ... }
O namespace desparece e dá lugar a um sobrenome para o tipo. Então, apesar de ser uma boa ideia ver o namespace como uma caixa que agrupam tipos, essa ideia passa uma impressão errada do conceito.
Pense bem, se fosse uma caixa de verdade, você poderia ter essa caixa separada em vários pedaços? Ou pior, você poderia ter a mesma caixa em vários lugares? Fisicamente é impossível. E o namespace permite isto. Então ele não é uma caixa, ele é um sobrenome. Você pode ter a mesma família (mesmo sobrenome) separada em vários lugares. Alguns membros estão em um lugar (um arquivo fonte) e outros estão em outro. De fato recomenda-se ter apenas um membro (um tipo) em cada arquivo).
Sobrenomes compostos
Você pode ter mais de um sobrenome. Por exemplo quando tem um namespace System.Collections
. Você está dizendo que o sobrenome é composto por duas palavras. Você não tem uma família chamada System
e dentro desta família uma sub-família chamada Collections
. Algumas pessoas podem entender que colocando um using System
no seu fonte incluirá todos os tipos do System.Collections
e esta ideia é errada. São coisas (famílias) independentes. Não há um conceito de árvore de namespaces. Já que não são caixas, os namespaces não podem estar uns dentro dos outros.
Economizando digitação
A vantagem de ser considerado algo separado do nome do tipo e não parte integrante é que você pode usar esses tipos sem o sobrenome, desde que indique em que família deve-se procurar pelo membro (pelo tipo). Isto é feito com a diretiva using
. Mais informações nessa resposta.
A ideia de que o using
funciona como um include
não é verdadeira. Pode-se pensar assim para facilitar o entendimento, mas na realidade o mais próximo do include
que se faz em .NET é incluir um assembly no projeto (criar uma referência para ele). Manualmente seria incluir algo assim:
<References>
<Reference
Name = "Lib1"
AssemblyName = "Lib1"
HintPath = "\\BuildServer\Latest\Release\SharedComponent\SomeControl.dll"
/>
</References>
Módulos no .NET
Em C#, ou .NET como um todo, é possível ter o conceito de caixa real. Isto é feito através do assembly. Veja mais nesta resposta.
A ideia do include é mais próxima aos pacotes do Java. Embora o package
do Java é uma conjunção do assembly e do namespace encontrado no C# e VB.NET. Essas linguagens separam os conceitos.
Conclusão
É preciso entender o que são agrupamentos lógicos. Isto não é um conceito da linguagem, mas uma forma de organizar seus projetos. Provavelmente você vai querer organizar tudo que faz parte do Estoque
em um mesmo namespace, todos fazem parte da família Estoque
. Algumas pessoas podem ficar tentadas a agrupar todos os Forms
s da aplicação em um mesmo namespace mas isto normalmente seria um erro. Você está colocando membros estranhos na mesma família só porque eles "exercem a mesma profissão".