C#: Espaços de nomes e a palavra-chave `using`
1. O que é um namespace
Um namespace é um mecanismo de agrupamento lógico utilizado para organizar o código e evitar conflitos de nomes de tipos. Em projetos de grande porte, diferentes módulos podem definir classes com o mesmo nome; os namespaces fornecem um caminho qualificado para os tipos.
2. Definição de namespace
Use a palavra-chave namespace para declarar um namespace, com os tipos colocados entre chaves.
▶ Exemplo
namespace MyApp.Models
{
public class User
{
public string Name { get; set; }
public int Age { get; set; }
}
}
namespace MyApp.Services
{
public class UserService
{
public string GetInfo()
{
return "UserService is ready";
}
}
}
3. Aninhamento de namespaces
Os namespaces podem ser aninhados, sendo que os namespaces internos são subespaços dos externos. O acesso por notação de ponto é equivalente à estrutura aninhada.
▶ Exemplo
namespace Company
{
namespace Products
{
namespace Electronics
{
public class Phone
{
public string Model { get; set; }
}
}
}
}
namespace Company.Products.Electronics
{
public class Tablet
{
public string Model { get; set; }
}
}
Company.Products.Electronics.Phone e Company.Products.Electronics.Tablet pertencem ao mesmo namespace.
4. Espaços de nomes no âmbito do arquivo (C# 10)
O C# 10 introduziu os namespaces com escopo de arquivo, que utilizam um ponto-e-vírgula no final. Todo o arquivo passa a fazer parte automaticamente desse namespace, reduzindo a indentação de aninhamento.
▶ Exemplo
namespace MyApp.Services;
public class EmailService
{
public void Send(string to)
{
System.Console.WriteLine($"Sending email to {to}");
}
}
Sending email to user@example.com
5. Uso da diretiva
A diretiva using importa um namespace para que você possa usar seus tipos diretamente, sem precisar escrever o nome totalmente qualificado.
▶ Exemplo
using System;
namespace MyApp
{
class Program
{
static void Main()
{
Console.WriteLine("No need for System.Console");
Console.WriteLine(DateTime.Now.Year);
}
}
}
No need for System.Console
2026
6. Como usar o Alias
Quando um namespace é muito longo ou há conflitos entre nomes de tipos, você pode usar using ... = ... para criar um alias.
▶ Exemplo
using Dict = System.Collections.Generic.Dictionary`<string, int>`;
using StringBuilder = System.Text.StringBuilder;
namespace MyApp
{
class Program
{
static void Main()
{
Dict scores = new Dict();
scores.Add("Alice", 95);
scores.Add("Bob", 87);
StringBuilder sb = new StringBuilder();
foreach (var pair in scores)
{
sb.AppendLine($"{pair.Key}: {pair.Value}");
}
System.Console.WriteLine(sb.ToString());
}
}
}
Alice: 95
Bob: 87
7. uso de static (C# 6)
using static importa os membros estáticos de um tipo, permitindo que você os chame sem o nome do tipo.
▶ Exemplo
using static System.Console;
using static System.Math;
namespace MyApp
{
class Program
{
static void Main()
{
WriteLine($"PI = {PI}");
WriteLine($"Max = {Max(10, 20)}");
WriteLine($"Sqrt(144) = {Sqrt(144)}");
}
}
}
PI = 3.14159265358979
Max = 20
Sqrt(144) = 12
8. Uso global (C# 10)
A declaração de global using em um arquivo torna o namespace disponível em todos os arquivos do projeto, eliminando a necessidade de repetir using.
▶ Exemplo
global using System;
global using System.Collections.Generic;
global using System.Linq;
É prática comum colocar as declarações de uso globais em um arquivo GlobalUsings.cs para gerenciamento centralizado.
9. Usos implícitos (C# 10)
Ao ativar <ImplicitUsings>enable</ImplicitUsings> no arquivo do projeto, os projetos no estilo SDK passam a adicionar automaticamente as instruções using globais para os namespaces mais comuns.
▶ Exemplo
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
Os projetos de console incluem automaticamente estes namespaces: System, System.Collections.Generic, System.IO, System.Linq, System.Threading, System.Threading.Tasks, etc.
10. uso de IDisposable
A instrução using garante que os objetos IDisposable liberem os recursos adequadamente após o uso. O C# 8 também oferece suporte à sintaxe de declaração “using”.
▶ Exemplo
using System;
using System.IO;
namespace MyApp
{
class Program
{
static void Main()
{
using (var fs = new FileStream("test.txt", FileMode.Create))
{
byte[] data = System.Text.Encoding.UTF8.GetBytes("Hello");
fs.Write(data, 0, data.Length);
}
using var reader = new StreamReader("test.txt");
Console.WriteLine(reader.ReadToEnd());
}
}
}
Hello
A forma entre chaves é liberada no final de seu escopo; using var é liberada no final do escopo que a contém.
11. Organização dos namespaces na Biblioteca de Classes do .NET
A biblioteca de classes do .NET organiza as funcionalidades em subespaços de nomes sob o namespace System.
▶ Exemplo
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MyApp
{
class Program
{
static void Main()
{
ArrayList list = new ArrayList { 1, 2, 3 };
List````<string>```` names = new List````<string>```` { "Alice", "Bob" };
var upper = names.Select(n => n.ToUpper());
StringBuilder sb = new StringBuilder("Count: ");
sb.Append(names.Count);
Console.WriteLine(sb.ToString());
}
}
}
Count: 2
| Espaço de nomes | Finalidade |
|---|---|
System |
Tipos básicos (Console, DateTime, Math, etc.) |
System.IO |
Operações com arquivos e fluxos |
System.Collections |
Coleções não genéricas (ArrayList, Hashtable) |
System.Collections.Generic |
Coleções genéricas (List<T>, Dictionary`<K,V>`) |
System.Linq |
Extensões de consulta LINQ |
System.Text |
Processamento de strings (StringBuilder, Encoding) |
System.Threading |
Threads e sincronização |
System.Threading.Tasks |
Programação assíncrona (Task, Task<T>) |
❓ Perguntas Frequentes
P: Espaços de nomes e assemblies (DLLs) são o mesmo conceito? R: Não. Espaços de nomes são uma organização lógica; assemblies são uma implantação física. Um assembly pode conter vários espaços de nomes, e um espaço de nomes pode abranger vários assemblies.
P: A diretiva
usingaumenta o tamanho do programa? R: Não. A diretivausingé apenas um recurso sintático para simplificar a notação durante a compilação e não tem efeito sobre o tempo de execução nem sobre o tamanho do programa.
P: É possível aninhar subespaços de nomes dentro de um espaço de nomes com escopo de arquivo? R: Sim, é possível definir subespaços de nomes entre chaves dentro de um espaço de nomes com escopo de arquivo.
P: Qual é a diferença entre o
global usinge oImplicitUsings? R: Oglobal usingé declarado manualmente pelo desenvolvedor; oImplicitUsingsé um conjunto deusings globais gerados automaticamente pelo SDK, que se baseia no mecanismo doglobal using.
P: O comando
usingestático permite importar membros de instância? R: Não, o comandousingestático importa apenas membros estáticos e tipos aninhados. Os membros de instância ainda precisam ser chamados por meio de um objeto.
📖 Resumo
- Os namespaces são definidos com
namespace, permitindo o aninhamento de chaves e a notação por ponto - A diretiva
usingimporta um namespace, eliminando nomes totalmente qualificados using Alias = FullTypeNameresolve conflitos de nomes ou simplifica nomes longosusing staticimporta os membros estáticos de um tipo para chamada diretaglobal usingé válido para todo o projeto, evitando repetições em cada arquivo- O namespace no âmbito do arquivo
namespace X;reduz os níveis de recuo - As utilizações implícitas incluem automaticamente os namespaces comuns por meio da configuração do projeto
- As instruções/declarações
usingservem para a liberação de recursos do tipo IDisposable - A biblioteca de classes do .NET está dividida em subespaços de nomes System de acordo com a funcionalidade
📝 Exercícios
- Crie uma classe
Teacherem um namespace aninhado de dois níveisSchool.Teacherse instancie-a emMain - Use um alias
usingpara criar um alias curto paraSystem.Collections.Generic.List``<string>, e depois use-o para criar uma lista, adicionar elementos e exibi-los - Use
using static System.Mathpara chamar diretamenteSqrt,AbseRounde exibir os resultados - Crie um arquivo
GlobalUsings.cscom as declaraçõesglobal usingparaSystem,System.IOeSystem.Linq; em seguida, omita essas instruçõesusingem outro arquivo para verificar se funcionam - Utilize tanto a abordagem com a instrução entre chaves
usingquanto a abordagem com a declaraçãousing varpara gravar em um arquivo comStreamWritere observe a diferença