The nameof operator C# 6.0 previously could only be used with generic types when all type arguments were specified. This meant you couldn't get the name of a generic type definition itself without providing type arguments, even when you didn't care about the specific type.
C# 14.0 allows nameof
to work with unbound generic types using the <>
syntax, making it possible to get the name of generic type definitions without needing to specify type arguments.
Code
C#
// Works with unbound generic types
string listName = nameof(List<>); // "List`1"
string dictName = nameof(Dictionary<,>); // "Dictionary`2"
string funcName = nameof(Func<,,,>); // "Func`4"
// Useful for reflection and logging
Type listType = typeof(List<>);
string name = nameof(List<>);
Console.WriteLine($"Working with {name}");
// Works with custom generic types
class MyGeneric<T, U> { }
string myName = nameof(MyGeneric<,>); // "MyGeneric`2"
C#
// Had to specify type arguments even when arbitrary
string listName = nameof(List<int>); // "List"
string dictName = nameof(Dictionary<int, string>); // "Dictionary"
string funcName = nameof(Func<int, int, int, int>); // "Func"
// Or use typeof with .Name
string name = typeof(List<>).Name; // "List`1"
Console.WriteLine($"Working with {name}");
// Same issue with custom types
class MyGeneric<T, U> { }
string myName = nameof(MyGeneric<int, string>); // "MyGeneric"
Notes
- Use
<>
for single type parameter,<,>
for two,<,,>
for three, etc. - The result includes the backtick notation (e.g.,
List
1`) that indicates the number of type parameters - This aligns
nameof
behavior withtypeof
for unbound generic types - Particularly useful in generic code, reflection scenarios, and logging frameworks
- The number of commas matches the number of type parameters minus one