I would expect some details about the type parameters
The "spec" says:
Result of nameof. The result of nameof depends on the symbols that its argument bound to:
One or more members: if all members have the same metadata name then the result of nameof is that name; otherwise it is an error "This argument refers to multiple elements with different names". The metadata name of a member I or
I< isA1...AK>` is simply "I" after standard identifier transformations have been applied.
Параметр <T>
удаляется за счет стандартных преобразований идентификаторов (раздел §2.4.2 в C# спецификации), которые не позволяют <>
, как действительные идентификаторы. Сначала удаляется любое из ведущих @, затем удаляются последовательности Unicode, а затем удаляются любые символы форматирования. Это, конечно же, происходит во время компиляции. Вы также можете увидеть это при попытке распечатать имя универсального типа:
typeof(List<string>).Name;
приведет к:
List`1
Is this because nameof is a compile-time construct and generics are types initialized at runtime? Or is there some other limitation?
Уточняется вторая ошибка недействительной конструкции, чтобы избежать осложнения разрешение перегрузки внутри nameof
:
Allow generic type arguments? Presumably 'yes' when naming a type since that's how expression binding already works. And presumably 'no.' when naming a method-group since type arguments are used/inferred during overload resolution, and it would be confusing also to have to deal with that in nameof.
Мы можем видеть, что явно в т он roslyn codebase:
private BoundExpression BindNameofOperatorInternal(InvocationExpressionSyntax node,
DiagnosticBag diagnostics)
{
CheckFeatureAvailability(node.GetLocation(), MessageID.IDS_FeatureNameof, diagnostics);
var argument = node.ArgumentList.Arguments[0].Expression;
string name = "";
// We relax the instance-vs-static requirement for top-level member access expressions by creating a NameofBinder binder.
var nameofBinder = new NameofBinder(argument, this);
var boundArgument = nameofBinder.BindExpression(argument, diagnostics);
if (!boundArgument.HasAnyErrors && CheckSyntaxForNameofArgument(argument, out name, diagnostics) && boundArgument.Kind == BoundKind.MethodGroup)
{
var methodGroup = (BoundMethodGroup)boundArgument;
if (!methodGroup.TypeArgumentsOpt.IsDefaultOrEmpty)
{
// method group with type parameters not allowed
diagnostics.Add(ErrorCode.ERR_NameofMethodGroupWithTypeParameters, argument.Location);
}
else
{
nameofBinder.EnsureNameofExpressionSymbols(methodGroup, diagnostics);
}
}
return new BoundNameOfOperator(node, boundArgument, ConstantValue.Create(name), Compilation.GetSpecialType(SpecialType.System_String));
}