Before C# 14, nameof required type arguments for generic types, even when you only needed the simple name. For example, nameof(List<int>) produces "List", even though the specific type argument does not affect the result. C# 14 lets you leave the type argument out:
using System.Collections.Generic;
// Works in earlier C# versions too.
const string withTypeArgument = nameof(List<int>); // "List"
// C# 14 or later.
const string withoutTypeArgument = nameof(List<>); // "List"
const string dictionaryName = nameof(Dictionary<,>); // "Dictionary"
List<> is an unbound generic type: you name the generic type without supplying its type arguments. For Dictionary<,>, the comma marks the two type parameter positions.
The result is still the simple type name. nameof(List<>) produces "List", without a namespace or generic syntax. The compiler resolves it to a string constant. It does not create a collection or inspect a type at runtime.
This is useful for a diagnostic message that names a generic type. You can reference the type directly instead of picking an arbitrary type argument just to satisfy the compiler.
Use this syntax when your project uses C# 14 or later and you only need the simple name. Keep the type arguments when compiling with an earlier language version. If you need to distinguish List<int> from List<string>, nameof cannot do that: both produce "List".