HOWTO · Csharp

Equivalente de typedef em C#

Aprenda o equivalente de typedef em C# com aliases using, com aliases de tuplas do C# 12 e aliases comuns para tipos genéricos.

Nesta página

C# não tem a palavra-chave typedef. A alternativa mais próxima é um alias using, que dá um nome local ao arquivo para um namespace ou tipo existente.

Um alias melhora a legibilidade, mas não cria um novo tipo em tempo de execução. Use uma classe, um record ou uma estrutura quando precisar de um tipo distinto com comportamento ou validação próprios.

Usar um alias using para um tipo existente

Coloque o alias junto das outras diretivas using no início do arquivo e use um destino totalmente qualificado. Assim, o alias não depende de outra diretiva.

Por exemplo, using RouteTable = System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<int>>; nomeia um tipo genérico fechado existente.

RouteTable é apenas uma forma curta de Dictionary<string, List<int>>. Ele não adiciona segurança de tipos nem cria uma nova declaração. Um alias normal vale no arquivo-fonte, não automaticamente em todo o projeto.

As formas de using têm funções diferentes: using System.Text; importa um namespace, using static System.Math; importa membros estáticos e using RouteTable = ...; cria um alias.

Aliases de tuplas do C# 12 e aliases de tipos genéricos

O C# 12 ampliou os aliases using para tipos que antes não tinham nome, como tuplas. Aliases comuns para tipos nomeados e tipos genéricos construídos já eram compatíveis. O exemplo a seguir usa as duas formas:

using RouteTable = System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<int>>;
using Coordinate = (double Latitude, double Longitude);

RouteTable routes = new() { ["home"] = [1, 2] };
Coordinate point = (52.37, 4.90);

System.Console.WriteLine($"{routes["home"].Count}:{point.Latitude:F2}");
2:52.37

Este caso de sucesso foi restaurado e compilado em um ambiente .NET 10.0.401 isolado e sem rede. O projeto foi copiado para o armazenamento temporário do contêiner, restaurado com --ignore-failed-sources e executado sem alterar o fixture ou a imagem.

Se o projeto usar C# 11 ou anterior, não presuma que aliases de formas arbitrárias compilarão. Atualize as ferramentas ou escreva o tipo completo. Aliases de tipos nomeados são anteriores ao C# 12.

O que um alias não faz

Um alias não é um tipo distinto no estilo de typedef. RouteTable e o tipo Dictionary completo são intercambiáveis na compilação. Se um valor não deve ser confundido com outro, use um tipo de domínio real, como um record ou uma estrutura.

Da mesma forma, um alias de tupla apenas dá um nome legível a uma forma de tupla; não a transforma em uma classe nomeada. Os nomes dos elementos ajudam o acesso e a documentação, mas não oferecem identidade de tipo independente.

Destinos de referência anulável são um limite

A gramática expandida de aliases ainda tem restrições. Um tipo de referência anulável no nível superior não pode ser o destino de um alias. Portanto, using MaybeName = string?; é intencionalmente inválido.

O compilador rejeita a declaração porque string? é uma anotação de referência anulável, não um destino permitido nessa posição. O fixture de limite deve falhar na compilação; ele é evidência diagnóstica, não uma solução executável.

Quando definir um tipo real

Escolha uma classe, um record ou uma estrutura quando o nome precisar representar um conceito distinto. Isso é adequado para invariantes, validação, métodos, construção controlada, igualdade ou uma API pública. Use um alias quando precisar apenas de uma escrita mais curta e local ao arquivo.

Consulte a documentação oficial da Microsoft sobre a diretiva using, C# 12 e a proposta de aliases using.

Perguntas frequentes

  1. C# oferece suporte a typedef? Não. Use um alias using ou um tipo real.
  2. Um alias pode nomear uma tupla? Sim, a partir do C# 12.
  3. O alias fica disponível em todos os arquivos? Não, um alias normal fica apenas no arquivo que o declara.
  4. Ele cria um novo tipo? Não, ele aponta para o tipo existente.
  5. Por que using MaybeName = string?; falha? Uma referência anulável de nível superior é proibida como destino.