HOWTO · Csharp

typedef Equivalent in C#

Learn the C# equivalent of typedef with using aliases, including C# 12 tuple aliases and ordinary aliases for generic types.

On this page

C# has no typedef keyword. The closest equivalent is a using alias, which gives a file-local name to an existing namespace or type:

The general form is using AliasName = Fully.Qualified.TypeName;.

An alias improves readability, but it does not create a new runtime type. Use a class, record, or struct when you need a distinct type with its own behavior or validation.

Use a using alias for an existing type

Place the alias with the other using directives at the top of the file. Use a fully qualified target so that the alias does not depend on another using directive:

For example, using RouteTable = System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<int>>; names an existing closed generic type.

RouteTable is only a shorter spelling for Dictionary<string, List<int>>; it does not add type safety or create a new declaration. The alias is available throughout this source file, not automatically throughout the project.

The familiar forms of using have different purposes. using System.Text; imports a namespace, using static System.Math; imports static members, and using RouteTable = ...; creates an alias. Do not confuse the first two forms with a type alias.

C# 12 tuple aliases and generic type aliases

C# 12 expanded using aliases to previously unnamed type forms such as tuples. Ordinary aliases for named and constructed generic types were already supported. The following example uses both forms:

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

This success case was restored and built in an isolated, network-disabled .NET 10.0.401 environment using the C# 12 language feature. The project fixture was copied to temporary container storage, restored with --ignore-failed-sources, and run without changing the source fixture or the image. The alias names are still file-scoped, even though the underlying tuple and generic types can be used elsewhere without aliases.

If the project targets C# 11 or an earlier language version, do not assume that aliases for arbitrary type forms will compile. Upgrade the language/toolchain or use the fully written type. The ordinary alias form for named types predates C# 12.

What an alias does not do

An alias is not a typedef-style distinct type. RouteTable and its full dictionary type are interchangeable at compile time. Code that needs a value which cannot accidentally be passed where another value is expected should use a real domain type, such as a record or readonly struct, rather than an alias.

Likewise, a tuple alias gives a readable name to a tuple shape; it does not turn that tuple into a named class. Tuple element names improve access and documentation, but they do not provide independent type identity.

Nullable-reference alias targets are a boundary

The expanded alias grammar still has restrictions. A top-level nullable reference type is not a permitted alias target. For example, this is intentionally invalid:

The invalid declaration is using MaybeName = string?;.

The compiler rejects the alias declaration because string? is a nullable-reference annotation, not an allowed alias target in this position. The boundary fixture is expected to fail compilation; it is diagnostic evidence, not a runnable solution. Use an allowed underlying type in the alias, and express nullability on the member, parameter, or variable where the alias is used.

When to define a real type instead

Choose a class, record, or struct when the name must represent a distinct concept. A real type is appropriate when you need invariants, validation, methods, controlled construction, equality semantics, or a public API that should not expose the implementation type directly. A using alias is better when you only need a shorter file-local spelling for a long type, tuple, or closed generic type.

For the official syntax and version details, see the Microsoft documentation for the using directive, what is new in C# 12, and the C# 12 using-alias proposal.

FAQ

  1. Does C# support typedef? No. Use a using alias for a shorter name, or define a real type when you need type identity.
  2. Can an alias target a tuple? Yes, with C# 12 or later.
  3. Is an alias available in every file? No. A normal alias is scoped to the file that declares it.
  4. Does an alias create a new type? No. It refers to the existing target type.
  5. Why does using MaybeName = string?; fail? A top-level nullable-reference target is prohibited for a using alias, so the compiler reports a declaration error.