C# Namespaces e using

O .NET traz milhares de tipos prontos: Console, Math, StringBuilder, List<T>, File… E os seus programas vão criar mais um monte: Produto, Cliente, Pedido. Para não virar bagunça, cada tipo mora num namespace, uma espécie de "sobrenome". Nesta aula você vai entender por que o Console.WriteLine funciona sem você escrever nada antes, por que o StringBuilder não funciona, o que a linha using faz e como organizar os seus próprios tipos em namespaces.

Você vai aprender
  • O que é um namespace e o que é o nome completo de um tipo (System.Text.StringBuilder).
  • Como a diretiva using encurta esses nomes.
  • Quais using o .NET liga sozinho (os usings implícitos, ImplicitUsings) e como conferir a lista.
  • Como valer um using para o projeto inteiro com global using.
  • Como colocar os seus tipos num namespace, com chaves ou com o namespace de arquivo (namespace Lojinha;).
  • Como resolver dois tipos com o mesmo nome (apelidos) e chamar métodos sem o nome da classe (using static).
  • Os erros CS0246, CS0103, CS0104, CS1529, CS8915, CS8954 e CS8955.

Todos os programas desta aula rodaram na máquina da Ana (usuária ana, computador notebook), com o .NET 10 SDK (C# 14). Os arquivos soltos ficam em ~/cs e rodam com dotnet run arquivo.cs (aula Rodar com dotnet run). Os exemplos com vários arquivos usam um projeto em ~/projetos/Lojinha (aula Projetos).


A ideia: o sobrenome dos tipos

Na escola da Ana há duas meninas chamadas Júlia. Quando a professora chama "Júlia!", as duas olham. Para não ter confusão, a escola usa o nome completo: "Júlia do 6º A" e "Júlia do 7º B". Na maior parte do tempo, porém, dentro da sala do 6º A, todo mundo diz só "Júlia", porque ali só existe uma.

Em C# é igual:

  • Um namespace (em inglês, "espaço de nomes") é a "turma" do tipo. A classe StringBuilder mora no namespace System.Text.
  • O nome completo do tipo junta os dois com ponto: System.Text.StringBuilder. Esse nome nunca é ambíguo.
  • A diretiva using ("usando") é como dizer "estou dentro da sala do 6º A": depois de using System.Text;, basta escrever StringBuilder.

Namespaces podem ter vários níveis, separados por ponto, como pastas dentro de pastas: System, System.Text, System.Collections.Generic. Mas atenção: eles não são pastas de verdade no disco; são só nomes que o compilador usa para achar os tipos.

TipoNamespaceNome completo
ConsoleSystemSystem.Console
MathSystemSystem.Math
StringBuilderSystem.TextSystem.Text.StringBuilder
List<T>System.Collections.GenericSystem.Collections.Generic.List<T>
FileSystem.IOSystem.IO.File
CultureInfoSystem.GlobalizationSystem.Globalization.CultureInfo

1. O nome completo funciona sempre

Este programa monta um texto com o StringBuilder sem nenhum using. Cada tipo é escrito com o nome completo:

System.Text.StringBuilder texto = new System.Text.StringBuilder();
texto.Append("arroz");
System.Console.WriteLine(texto);
$ dotnet run completo.cs
arroz
System.Text.StringBuilder
O nome completo: namespace System.Text + tipo StringBuilder. Repare que ele aparece duas vezes na linha: no tipo da variável e depois do new.
System.Console.WriteLine
O mesmo para o Console: namespace System + tipo Console + método WriteLine.

Funciona, mas é cansativo de escrever e de ler. É para isso que existe o using.


2. A diretiva using

Agora sem o nome completo. A Ana escreveu StringBuilder direto:

Este código tem um erro de propósito.
var texto = new StringBuilder();
texto.Append("Lista da Ana: ");
texto.Append("arroz, feijão");
Console.WriteLine(texto);
$ dotnet run sb.cs
/home/ana/cs/sb.cs(1,17): error CS0246: O nome do tipo ou do namespace "StringBuilder" não pode ser encontrado (está faltando uma diretiva using ou uma referência de assembly?)

Ocorreu uma falha no build. Corrija os erros de build e execute novamente.

"O nome do tipo ou do namespace StringBuilder não pode ser encontrado." Em inglês, para pesquisar: The type or namespace name 'StringBuilder' could not be found. O compilador procurou um tipo chamado só StringBuilder nos namespaces que ele conhece naquele arquivo e não achou. O próprio erro dá a dica: "está faltando uma diretiva using?". Está:

using System.Text;

var texto = new StringBuilder();
texto.Append("Lista da Ana: ");
texto.Append("arroz, feijão");
Console.WriteLine(texto);
$ dotnet run sb.cs
Lista da Ana: arroz, feijão
using
"Usando": avisa o compilador para procurar tipos também neste namespace.
System.Text
O namespace. É o nome completo sem o tipo no fim.
;
Termina a diretiva.
(no topo)
As diretivas using ficam no começo do arquivo, antes de qualquer outra coisa. Fora do lugar, dão o erro CS1529 (veja Quando dá errado).
using não "carrega" nada

Quem vem de outras linguagens às vezes acha que o using "importa" ou "inclui" uma biblioteca. Não é isso: ele só encurta nomes. O programa com using System.Text; e o programa com System.Text.StringBuilder escrito por extenso são exatamente o mesmo programa depois de compilados. Um using a mais não deixa o programa mais lento nem maior.

using System; não liga o System.Text

Como os nomes parecem pastas, é natural achar que using System; traz tudo o que começa com System. Não traz: cada using vale para um namespace, sem os "de dentro". Para usar StringBuilder, é preciso using System.Text;, mesmo que System já esteja ligado.

A palavra using tem outro uso em C#, bem diferente: o comando using (…), que fecha arquivos e conexões. Esse fica para a aula using e IDisposable. Nesta aula, using é sempre a diretiva do topo do arquivo.

Missão: rode e veja o erro CS0246. Depois acrescente, na primeira linha, a diretiva using do namespace do StringBuilder e rode de novo.

var texto = new StringBuilder();
texto.Append("Lista da Ana: ");
texto.Append("arroz, feijão");
Console.WriteLine(texto);
using System.Text;

var texto = new StringBuilder();
texto.Append("Lista da Ana: ");
texto.Append("arroz, feijão");
Console.WriteLine(texto);

3. Os usings implícitos (ImplicitUsings) .NET 6+

Se o StringBuilder precisa de using, por que o Console não precisa? O Console mora em System, e ninguém escreveu using System;…

A resposta: desde o .NET 6, o próprio dotnet acrescenta alguns using sozinho, sem aparecer no seu arquivo. São os usings implícitos (implicit usings). Dá para ver a lista: o dotnet run ola.cs monta um projeto escondido em ~/.local/share/dotnet/runfile/, e lá dentro há um arquivo gerado com eles:

$ dotnet run ola.cs
Olá, mundo!
$ cat ~/.local/share/dotnet/runfile/ola-*/obj/debug/ola.GlobalUsings.g.cs
// <auto-generated/>
global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Linq;
global using System.Net.Http;
global using System.Threading;
global using System.Threading.Tasks;

São sete namespaces, ligados em todo programa console do .NET 10:

NamespaceO que traz (exemplos)Aula
SystemConsole, Math, Random, DateTime, int.Parse, as exceções básicasSaída
System.Collections.GenericList<T>, Dictionary<TKey, TValue>, HashSet<T>Coleções
System.IOFile, Directory, Path, StreamReaderArquivos
System.LinqWhere, Select, Sum, OrderByLINQ
System.Net.HttpHttpClient (baixar páginas da internet)—
System.ThreadingThread, CancellationTokenThreads
System.Threading.TasksTask, ParallelTask

Tudo o que estiver fora dessa lista precisa de using: System.Text (StringBuilder), System.Globalization (CultureInfo), System.Text.Json, System.Text.RegularExpressions (Regex), System.Diagnostics (Stopwatch)…

De onde vem essa lista

Num projeto criado com dotnet new console, a chave fica à vista, no arquivo .csproj (aula O Arquivo .csproj):

$ cat Lojinha.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

<ImplicitUsings>enable</ImplicitUsings> quer dizer "usings implícitos: ligados". O dotnet run arquivo.cs usa a mesma configuração, só que sem mostrar o .csproj. Num projeto, a lista gerada fica em obj/Debug/net10.0/Lojinha.GlobalUsings.g.cs, com os mesmos sete.

Para ver o que acontece sem eles, a Ana desligou a chave no próprio arquivo, com uma diretiva #:property (só existe nos arquivos rodados com dotnet run arquivo.cs):

#:property ImplicitUsings=disable
Console.WriteLine("Olá");
$ dotnet run semimp.cs
/home/ana/cs/semimp.cs(2,1): error CS0103: O nome "Console" não existe no contexto atual

Ocorreu uma falha no build. Corrija os erros de build e execute novamente.

Sem o using System; implícito, o compilador não sabe mais quem é Console. É assim que eram todos os programas antes do .NET 6: o arquivo começava com uma fileira de using. Você ainda vai ver muito código assim em livros e na internet:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Lojinha
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Olá");
        }
    }
}

Com os usings implícitos ligados, escrever using System; de novo não dá erro nem aviso: é só redundante. A aula Program.cs e o Main explica o resto desse modelo antigo.


4. global using: um using para o projeto inteiro C# 10

Um using normal vale só no arquivo em que foi escrito. Num projeto com dez arquivos que usam StringBuilder, seriam dez using System.Text;. A palavra global resolve isso: global using vale para todos os arquivos do projeto. Os usings implícitos, aliás, são exatamente isso: as sete linhas global using do arquivo gerado.

A lojinha da Ana virou um projeto com uma pasta Modelos. O arquivo Etiqueta.cs usa StringBuilder:

namespace Lojinha.Modelos;

public static class Etiqueta
{
    public static string Montar(Produto p)
    {
        var sb = new StringBuilder();
        sb.Append(p.Nome.ToUpper());
        sb.Append(" ... ");
        sb.Append(p.Preco.ToString("C"));
        return sb.ToString();
    }
}

(A primeira linha, namespace Lojinha.Modelos;, é explicada na próxima seção.) Sem using System.Text;, o erro já é conhecido; repare que agora ele aponta o arquivo dentro da pasta e, no fim, o projeto entre colchetes:

$ dotnet run
/home/ana/projetos/Lojinha/Modelos/Etiqueta.cs(7,22): error CS0246: O nome do tipo ou do namespace "StringBuilder" não pode ser encontrado (está faltando uma diretiva using ou uma referência de assembly?) [/home/ana/projetos/Lojinha/Lojinha.csproj]

Ocorreu uma falha no build. Corrija os erros de build e execute novamente.

A Ana criou um arquivo só para os usings globais. O nome GlobalUsings.cs é costume, não obrigação:

global using System.Text;
$ dotnet run
CADERNO ... R$ 12,50

Pronto: System.Text passou a valer em Program.cs, em Modelos/Etiqueta.cs e em qualquer arquivo novo.

A outra forma: no .csproj

Em vez do arquivo GlobalUsings.cs, dá para pedir o mesmo no .csproj, com um item <Using>:

$ cat Lojinha.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <Using Include="System.Text" />
  </ItemGroup>

</Project>
$ dotnet run
CADERNO ... R$ 12,50
$ tail -3 obj/Debug/net10.0/Lojinha.GlobalUsings.g.cs
global using System.Text;
global using System.Threading;
global using System.Threading.Tasks;

O dotnet acrescentou global using System.Text; ao arquivo gerado, junto com os sete de sempre. As duas formas dão o mesmo resultado; escolha uma por projeto e use sempre ela, para ninguém precisar procurar em dois lugares.

Sem exagero

global using é bom para o que quase todo arquivo usa. Para algo que só um ou dois arquivos usam (System.Text.Json, por exemplo), um using normal no próprio arquivo deixa mais claro de onde vêm os tipos.

Missão: este "projeto" tem três abas. A Etiqueta.cs usa StringBuilder e não compila. Sem mexer nela, escreva na aba GlobalUsings.cs um global using que conserte o projeto inteiro.

using Lojinha.Modelos;

var caderno = new Produto("Caderno", 12.50m);
Console.WriteLine(Etiqueta.Montar(caderno));
namespace Lojinha.Modelos;

public record Produto(string Nome, decimal Preco);

public static class Etiqueta
{
    public static string Montar(Produto p)
    {
        var sb = new StringBuilder();
        sb.Append(p.Nome.ToUpper());
        sb.Append(" ... ");
        sb.Append(p.Preco.ToString("C"));
        return sb.ToString();
    }
}
// escreva aqui o global using
global using System.Text;

5. Os seus tipos num namespace

Até aqui, os tipos que você criou (classes, records) ficaram sem namespace, no chamado namespace global. Para programas de um arquivo, tudo bem. Num projeto de verdade, cada tipo deve morar num namespace com o nome do projeto, como Lojinha ou Lojinha.Modelos. Há duas formas de escrever isso.

Com chaves: namespace Nome { … }

A forma clássica abre um bloco, e tudo o que estiver dentro das chaves pertence ao namespace:

using Lojinha;

var p = new Produto("Caderno", 12.50m);
Console.WriteLine($"{p.Nome}: {p.Preco:C}");
Console.WriteLine(typeof(Produto).FullName);
Console.WriteLine(typeof(Produto).Namespace);

namespace Lojinha
{
    record Produto(string Nome, decimal Preco);
}
$ dotnet run loja.cs
Caderno: R$ 12,50
Lojinha.Produto
Lojinha
using Lojinha;
O código de cima (as instruções de nível superior) fica no namespace global. Para enxergar Produto só pelo nome curto, ele precisa deste using, como para qualquer namespace do .NET.
typeof(Produto).FullName
typeof dá informações sobre um tipo (aula Reflexão). FullName é o nome completo: Lojinha.Produto.
typeof(Produto).Namespace
Só o namespace: Lojinha.
namespace Lojinha
Abre o namespace Lojinha.
{ record Produto(…); }
Tudo dentro das chaves pertence a Lojinha. Pode haver vários tipos ali dentro.

Num arquivo rodado com dotnet run arquivo.cs, as instruções de nível superior vêm primeiro, e os namespaces com chaves vêm depois delas, no fim do arquivo.

O namespace de arquivo: namespace Nome; C# 10

Quase sempre, um arquivo inteiro pertence a um namespace só. Para isso o C# 10 criou uma forma mais curta, o namespace de arquivo (file-scoped namespace): uma linha com ponto e vírgula, sem chaves, e tudo o que vem depois no arquivo pertence a ele. É a forma que o guia usa nos projetos, e a que você vai ver em código novo:

namespace Lojinha.Modelos;

public record Produto(string Nome, decimal Preco);
using Lojinha.Modelos;

var caderno = new Produto("Caderno", 12.50m);
Console.WriteLine($"{caderno.Nome}: {caderno.Preco:C}");
$ dotnet run
Caderno: R$ 12,50
namespace Lojinha.Modelos;
"Daqui até o fim do arquivo, tudo é do namespace Lojinha.Modelos." Economiza um nível de recuo em todo o arquivo.
public record Produto(…)
O nome completo do tipo passa a ser Lojinha.Modelos.Produto. O public deixa outros projetos usarem o tipo (aula public, private e internal).
using Lojinha.Modelos;
No Program.cs, que está em outro arquivo, o using faz Produto valer sem o nome completo.
Com chavesDe arquivo
Sintaxenamespace Lojinha { … }namespace Lojinha;
Vale parao que está dentro das chaveso arquivo todo, da linha para baixo
Quantos por arquivováriosum só (e não se mistura com o de chaves)
Com instruções de nível superiorsim, depois delasnão (o arquivo do Program.cs fica sem namespace)
DesdeC# 1C# 10 (.NET 6)

Os costumes dos programadores C#

  • O namespace começa com o nome do projeto e segue as pastas: o arquivo Modelos/Produto.cs do projeto Lojinha fica em Lojinha.Modelos. O compilador não obriga, mas todo mundo espera isso.
  • Nomes em PascalCase, como os tipos: Lojinha.Modelos, nunca lojinha.modelos.
  • Um tipo por arquivo, com o mesmo nome do tipo (Produto.cs guarda Produto).
  • Nunca dê ao namespace o mesmo nome de uma classe de dentro dele (Lojinha.Lojinha confunde o compilador e as pessoas).

O editor do guia compila todas as abas juntas, como um projeto. Assim, você pode praticar com um arquivo por tipo:

Missão: o Produto está no namespace Lojinha.Modelos (aba Produto.cs), mas o Program.cs não o encontra. Rode, leia o erro e conserte o Program.cs com uma diretiva using.

var caderno = new Produto("Caderno", 12.50m);
Console.WriteLine($"Etiqueta: {caderno.Nome}");
namespace Lojinha.Modelos;

public record Produto(string Nome, decimal Preco);
using Lojinha.Modelos;

var caderno = new Produto("Caderno", 12.50m);
Console.WriteLine($"Etiqueta: {caderno.Nome}");

6. Dois tipos com o mesmo nome

A lojinha cresceu. O controle de estoque tem um Produto com quantidade, e o caixa tem outro Produto com preço. Cada um no seu namespace, sem problema nenhum: os nomes completos são diferentes. O problema aparece quando um arquivo liga os dois:

Este código tem um erro de propósito.
using Lojinha.Estoque;
using Lojinha.Vendas;

var item = new Produto("Caneta");
Console.WriteLine(item);

namespace Lojinha.Estoque
{
    record Produto(string Nome);
}

namespace Lojinha.Vendas
{
    record Produto(string Nome);
}
$ dotnet run ambiguo.cs
/home/ana/cs/ambiguo.cs(4,16): error CS0104: "Produto" é uma referência ambígua entre "Lojinha.Estoque.Produto" e "Lojinha.Vendas.Produto"

Ocorreu uma falha no build. Corrija os erros de build e execute novamente.

"Referência ambígua" (is an ambiguous reference between): são as duas Júlias. O compilador não adivinha qual você quis. Três saídas:

  1. Nome completo na linha que usa: new Lojinha.Estoque.Produto("Caneta").
  2. Tirar um dos using, se o arquivo só precisa de um dos dois.
  3. Um apelido (alias), a forma mais legível quando o arquivo precisa dos dois.

Apelidos: using Apelido = Namespace;

using Estoque = Lojinha.Estoque;
using Vendas = Lojinha.Vendas;

var noDeposito = new Estoque.Produto("Caneta", 40);
var naNota = new Vendas.Produto("Caneta", 2.50m);
Console.WriteLine(noDeposito);
Console.WriteLine(naNota);

namespace Lojinha.Estoque
{
    record Produto(string Nome, int Quantidade);
}

namespace Lojinha.Vendas
{
    record Produto(string Nome, decimal Preco);
}
$ dotnet run apelido.cs
Produto { Nome = Caneta, Quantidade = 40 }
Produto { Nome = Caneta, Preco = 2,50 }
using Estoque = Lojinha.Estoque;
Cria o apelido Estoque para o namespace Lojinha.Estoque. Repare que ele não liga o namespace: Produto sozinho continua desconhecido. Só Estoque.Produto funciona.
new Estoque.Produto("Caneta", 40)
Lê-se "o Produto do estoque". Fica claro de qual dos dois se trata.
Console.WriteLine(noDeposito)
Um record mostra o nome do tipo e os valores (aula Records). O nome do tipo aparece curto, sem o namespace.

O apelido também pode ser de um tipo só: using ProdutoDoCaixa = Lojinha.Vendas.Produto;. Desde o C# 12, pode ser de qualquer tipo, até de uma tupla:

using Ponto = (int X, int Y);

Ponto p = (3, 4);
Console.WriteLine(p);
$ dotnet run tupla.cs
(3, 4)

A marca C# 12 vale para esse último caso (apelido de tupla, de array e de outros tipos sem nome). Apelidos de namespaces e de classes existem desde o C# 1.


7. using static: métodos sem o nome da classe C# 6

Há uma terceira forma de diretiva. using static recebe uma classe (não um namespace) e deixa você usar os membros estáticos dela sem escrever o nome da classe:

using static System.Math;
using static System.Console;

double raio = 2;
WriteLine(PI * Pow(raio, 2));
WriteLine(Max(3, 8));
$ dotnet run estatico.cs
12,566370614359172
8
using static System.Math;
PI, Pow e Max passam a valer sem o Math. na frente (aula Matemática).
using static System.Console;
WriteLine sem o Console..
12,566370614359172
A área do círculo de raio 2. A vírgula é a da cultura pt-BR da Ana (aula Cultura).

Use com moderação. Numa conta cheia de Math, ajuda. Mas quem lê WriteLine(…) num programa grande fica sem saber de onde ele veio. O guia continua escrevendo Console.WriteLine.


Formas diferentes, qual usar

SituaçãoForma
Usar um tipo uma vez, num lugar sóNome completo: System.Text.StringBuilder
Usar tipos de um namespace num arquivousing System.Text; no topo do arquivo
Um namespace que quase todo arquivo do projeto usaglobal using System.Text; num GlobalUsings.cs, ou <Using Include="System.Text" /> no .csproj
Console, listas, arquivos, LINQNada: já vêm nos usings implícitos
Os seus tipos num projetoNamespace de arquivo: namespace Lojinha.Modelos;
Tipos depois das instruções, num arquivo do dotnet run arquivo.csNamespace com chaves: namespace Lojinha { … }
Dois tipos com o mesmo nome no mesmo arquivoApelido: using Estoque = Lojinha.Estoque;
Conta com muitos Math.using static System.Math;

Quando dá errado

CS0246: "O nome do tipo ou do namespace … não pode ser encontrado"

Você já viu este erro com o StringBuilder. Ele também aparece quando o using tem um nome que não existe. A Ana escreveu Modelo em vez de Modelos:

using Lojinha.Modelo;
Console.WriteLine("oi");
$ dotnet run nsinex.cs
/home/ana/cs/nsinex.cs(1,7): error CS0246: O nome do tipo ou do namespace "Lojinha" não pode ser encontrado (está faltando uma diretiva using ou uma referência de assembly?)

Ocorreu uma falha no build. Corrija os erros de build e execute novamente.

O que significa: neste arquivo não existe nenhum namespace Lojinha. Com o tipo certo e o using faltando, o erro aponta o nome do tipo; com o using errado, aponta a própria linha do using (coluna 7).

Como consertar: confira a grafia do namespace (maiúsculas contam: lojinha ≠ Lojinha) e se ele existe mesmo. Para tipos do .NET, a documentação de cada tipo diz o namespace. Se for um pacote NuGet que ainda não foi instalado, falta o pacote, não o using (aula Pacotes NuGet).

CS0103: "O nome "Console" não existe no contexto atual"

O que significa: o compilador não sabe quem é Console. Num programa normal do .NET 10 isso não acontece, porque System vem nos usings implícitos. Se aconteceu, os usings implícitos estão desligados: <ImplicitUsings>disable</ImplicitUsings> no .csproj, #:property ImplicitUsings=disable no arquivo, ou um projeto antigo, de antes do .NET 6.

Como consertar: escreva using System; no topo, ou ligue de novo os usings implícitos (enable).

CS0104: "… é uma referência ambígua entre …"

O que significa: dois namespaces ligados por using têm um tipo com o mesmo nome.

Como consertar: use o nome completo, tire o using que sobra ou crie um apelido (using Estoque = Lojinha.Estoque;).

CS1529: using fora do lugar
Console.WriteLine("oi");
using System.Text;
$ dotnet run ordem.cs
/home/ana/cs/ordem.cs(2,1): error CS1529: Uma cláusula using deve preceder todos os outros elementos definidos no namespace, exceto as declarações de alias externas

Ocorreu uma falha no build. Corrija os erros de build e execute novamente.

O que significa: "uma cláusula using deve vir antes de todos os outros elementos". As diretivas ficam no topo do arquivo, antes das instruções e dos tipos.

Como consertar: suba a linha do using para o começo do arquivo.

CS8915: global using depois de um using normal
using System.Text;
global using System.Globalization;
Console.WriteLine("Olá");
$ dotnet run glob.cs
/home/ana/cs/glob.cs(2,1): error CS8915: Uma diretiva de uso global deve preceder todas as diretivas de uso não global.

Ocorreu uma falha no build. Corrija os erros de build e execute novamente.

O que significa: dentro de um arquivo, os global using vêm primeiro, depois os using normais.

Como consertar: inverta as duas linhas ou, melhor ainda, mova os global using para um arquivo só deles (GlobalUsings.cs).

CS8955 e CS8954: misturando as formas de namespace
namespace Lojinha;

namespace Outro
{
    class A { }
}
$ dotnet run misto.cs
/home/ana/cs/misto.cs(3,11): error CS8955: O arquivo de origem não pode conter declarações de namespace normal e escopo de arquivo.

Ocorreu uma falha no build. Corrija os erros de build e execute novamente.

E com dois namespaces de arquivo (namespace Lojinha; e, logo abaixo, namespace Outro;):

$ dotnet run dois.cs
/home/ana/cs/dois.cs(2,11): error CS8954: O arquivo de origem só pode conter uma declaração de namespace de escopo de arquivo.

Ocorreu uma falha no build. Corrija os erros de build e execute novamente.

O que significa: o namespace de arquivo vale para o arquivo inteiro, então não pode haver outro namespace no mesmo arquivo, nem de arquivo nem com chaves.

Como consertar: um namespace de arquivo por arquivo. Se precisa de dois namespaces, use dois arquivos, ou use só namespaces com chaves.

Namespace de arquivo junto com instruções de nível superior
namespace Lojinha;

Console.WriteLine("oi");

class Produto { }
$ dotnet run loja3.cs
/home/ana/cs/loja3.cs(3,9): error CS0116: Um namespace não pode conter diretamente membros, como campos, métodos ou instruções
/home/ana/cs/loja3.cs(3,19): error CS1026: ) esperado
/home/ana/cs/loja3.cs(3,19): error CS1022: Definição de namespace ou tipo, ou final do arquivo esperado

Ocorreu uma falha no build. Corrija os erros de build e execute novamente.

O que significa: três erros para um problema só. Depois de namespace Lojinha;, o arquivo inteiro está "dentro" do namespace, e um namespace só pode conter tipos (classes, records, structs…), não instruções soltas como o Console.WriteLine. O compilador se perde a partir dali, e os erros CS1026 e CS1022 são consequência do primeiro. Lembre a regra da aula Lendo Erros do Compilador: conserte o primeiro erro e rode de novo.

Como consertar: o arquivo com as instruções de nível superior fica sem namespace. Num projeto, coloque os tipos em outros arquivos, cada um com o seu namespace Lojinha;. Num arquivo só, use o namespace com chaves, no fim.

Aviso CS0105: o mesmo using duas vezes
$ dotnet run dup.cs
/home/ana/cs/dup.cs(3,7): warning CS0105: A diretiva using para "System.Text" apareceu anteriormente neste namespace
Olá

O que significa: é só um aviso (o programa rodou): a linha 3 repete um using System.Text; que já estava na linha 2. Apague a repetida.


Referência

SintaxeO que faz
System.Text.StringBuilderNome completo de um tipo: namespace + tipo
using System.Text;Liga um namespace neste arquivo: os tipos dele valem pelo nome curto
global using System.Text;Liga um namespace em todos os arquivos do projeto C# 10
<Using Include="System.Text" />O mesmo que o global using, escrito no .csproj
<ImplicitUsings>enable</ImplicitUsings>Liga os 7 usings implícitos (System, System.Collections.Generic, System.IO, System.Linq, System.Net.Http, System.Threading, System.Threading.Tasks)
#:property ImplicitUsings=disableDesliga os usings implícitos num arquivo do dotnet run arquivo.cs
namespace Lojinha { … }Os tipos dentro das chaves pertencem a Lojinha
namespace Lojinha.Modelos;Namespace de arquivo: o arquivo todo pertence a ele C# 10
using Estoque = Lojinha.Estoque;Apelido para um namespace ou tipo
using Ponto = (int X, int Y);Apelido para qualquer tipo, até tupla C# 12
using static System.Math;Membros estáticos da classe sem o nome dela C# 6
typeof(T).Namespace / .FullNameO namespace / o nome completo de um tipo
CS0246Tipo ou namespace não encontrado (falta using ou o nome está errado)
CS0103Nome não existe (com Console: usings implícitos desligados)
CS0104Referência ambígua: dois tipos com o mesmo nome
CS1529using depois de outro elemento
CS8915global using depois de um using normal
CS8954 / CS8955Dois namespaces de arquivo / namespace de arquivo misturado com o de chaves
CS0105 (aviso)using repetido

Exercícios

1. A diretiva

Complete para poder escrever StringBuilder sem o nome completo:

System.Text;

2. Para o projeto inteiro

Complete para que System.Globalization valha em todos os arquivos do projeto:

using System.Globalization;

3. Namespace de arquivo

Complete a primeira linha do arquivo Modelos/Cliente.cs do projeto Lojinha, seguindo o costume:

namespace

4. Num programa do .NET 10 com os usings implícitos ligados, qual destes tipos precisa de um using a mais?

5. O que a diretiva using System.Text; faz?

6. Um arquivo tem using Lojinha.Estoque; e using Lojinha.Vendas;, e os dois namespaces têm um tipo Produto. O que acontece em new Produto("Caneta")?

Missão final: o programa não compila por causa do CS0104. Troque as duas diretivas por apelidos (using Estoque = …; e using Vendas = …;) e mostre os dois produtos: o do estoque com 40 unidades e o do caixa com preço 2.50m.

using Lojinha.Estoque;
using Lojinha.Vendas;

var noDeposito = new Produto("Caneta", 40);
var naNota = new Produto("Caneta", 2.50m);
Console.WriteLine(noDeposito);
Console.WriteLine(naNota);

namespace Lojinha.Estoque
{
    record Produto(string Nome, int Quantidade);
}

namespace Lojinha.Vendas
{
    record Produto(string Nome, decimal Preco);
}
using Estoque = Lojinha.Estoque;
using Vendas = Lojinha.Vendas;

var noDeposito = new Estoque.Produto("Caneta", 40);
var naNota = new Vendas.Produto("Caneta", 2.50m);
Console.WriteLine(noDeposito);
Console.WriteLine(naNota);

namespace Lojinha.Estoque
{
    record Produto(string Nome, int Quantidade);
}

namespace Lojinha.Vendas
{
    record Produto(string Nome, decimal Preco);
}

Resumo

  • Todo tipo mora num namespace. O nome completo junta os dois: System.Text.StringBuilder.
  • using System.Text;, no topo do arquivo, deixa usar o nome curto. Ele só encurta nomes, não carrega nada, e não liga os namespaces "de dentro".
  • O .NET 10 liga sozinho 7 usings implícitos (ImplicitUsings): System, System.Collections.Generic, System.IO, System.Linq, System.Net.Http, System.Threading e System.Threading.Tasks. O resto (como System.Text) precisa de using.
  • global using vale para o projeto inteiro. Fica num GlobalUsings.cs ou no .csproj (<Using Include="…" />), e vem antes dos using normais (CS8915).
  • Os seus tipos: namespace Lojinha.Modelos; (namespace de arquivo, um por arquivo, sem instruções soltas) ou namespace Lojinha { … } (com chaves, depois das instruções de nível superior).
  • Dois tipos com o mesmo nome dão CS0104: use o nome completo ou um apelido (using Estoque = Lojinha.Estoque;).
  • using static System.Math; dispensa o nome da classe; use com moderação.