HOWTO · Csharp

Equivalente di typedef in C#

Scopri l’equivalente di typedef in C# con gli alias using, con gli alias di tuple di C# 12 e gli alias ordinari per i tipi generici.

In questa pagina

C# non dispone della parola chiave typedef. L’alternativa più vicina è un alias using, che assegna un nome locale al file a uno spazio dei nomi o tipo esistente.

Un alias migliora la leggibilità, ma non crea un nuovo tipo a runtime. Usa una classe, un record o una struttura quando ti serve un tipo distinto con comportamento o convalida propri.

Usare un alias using per un tipo esistente

Metti l’alias insieme alle altre direttive using all’inizio del file e usa una destinazione completamente qualificata. Così l’alias non dipende da un’altra direttiva.

Per esempio, using RouteTable = System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<int>>; assegna un nome a un tipo generico costruito esistente.

RouteTable è solo una forma abbreviata di Dictionary<string, List<int>>. Non aggiunge sicurezza dei tipi e non crea una nuova dichiarazione. Un alias normale è disponibile nel file sorgente, non automaticamente nell’intero progetto.

Le forme di using hanno scopi diversi: using System.Text; importa uno spazio dei nomi, using static System.Math; importa membri statici e using RouteTable = ...; crea un alias.

Alias di tuple di C# 12 e alias di tipi generici

C# 12 ha esteso gli alias using ai tipi precedentemente senza nome, come le tuple. Gli alias ordinari per tipi con nome e tipi generici costruiti erano già supportati. L’esempio seguente usa entrambe le forme:

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

Questo caso riuscito è stato ripristinato e compilato in un ambiente .NET 10.0.401 isolato e senza rete. Il progetto è stato copiato nello spazio temporaneo del container, ripristinato con --ignore-failed-sources ed eseguito senza modificare fixture o immagine.

Con C# 11 o una versione precedente, non dare per scontato che gli alias per forme arbitrarie compilino. Aggiorna gli strumenti o scrivi il tipo completo. Gli alias di tipi con nome sono precedenti a C# 12.

Cosa non fa un alias

Un alias non è un tipo distinto come un typedef. RouteTable e il tipo Dictionary completo sono intercambiabili in compilazione. Se un valore non deve essere confuso con un altro, serve un vero tipo di dominio, come un record o una struttura.

Allo stesso modo, un alias di tupla dà solo un nome leggibile a una forma di tupla; non la trasforma in una classe con nome. I nomi degli elementi aiutano l’accesso e la documentazione, ma non forniscono identità di tipo indipendente.

I destinatari nullable sono un limite

La grammatica estesa degli alias conserva alcune restrizioni. Un tipo di riferimento nullable al livello superiore non può essere il destinatario di un alias. Perciò using MaybeName = string?; è intenzionalmente non valido.

Il compilatore rifiuta la dichiarazione perché string? è un’annotazione nullable e non un destinatario ammesso in questa posizione. Il fixture limite deve fallire in compilazione: è una prova diagnostica, non una soluzione eseguibile.

Quando definire un tipo reale

Scegli una classe, un record o una struttura quando il nome deve rappresentare un concetto distinto. Sono adatti per invarianti, convalida, metodi, costruzione controllata, uguaglianza o API pubbliche. Usa un alias solo per una forma più breve e locale al file.

Consulta la documentazione Microsoft sulla direttiva using, C# 12 e la proposta degli alias using.

Domande frequenti

  1. C# supporta typedef? No. Usa un alias using o un tipo reale.
  2. Un alias può nominare una tupla? Sì, da C# 12.
  3. L’alias è disponibile in ogni file? No, un alias normale vale solo nel suo file.
  4. Crea un nuovo tipo? No, indica il tipo esistente.
  5. Perché using MaybeName = string?; fallisce? Un riferimento nullable di livello superiore è vietato come destinatario.