nameof 与泛型
nameof with Generics
我正在试验 nameof
泛型。我没有得到预期的结果。我不确定这是否是规范的一部分。
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ($"Hello { nameof(FooBar<string>)! }");
}
}
class FooBar<T> { }
我得到的输出是
Hello FooBar!
我希望获得有关类型参数的一些详细信息。
我尝试了一种方法,但由于编译器错误而失败:
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ($"Hello { nameof(Do<string>) }");
}
public static T Do<T>() {}
}
Error CS8084: An argument to nameof operator cannot be method group with type arguments (CS8084) (foo)
这是因为 nameof
是一个编译时构造,而泛型是在运行时初始化的类型吗?还是有其他限制?
I would expect some details about the type parameters
来自设计文档:
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 Ior
I< isA1...AK>` is simply "I" after standard
identifier transformations have been applied.
由于标准标识符转换(C# 规范中的第 2.4.2 节)不允许 <>
作为有效标识符,因此删除了 <T>
参数。首先删除任何前导 @,然后转换 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 代码库中清楚地看到:
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));
}
有关完整规范,请参阅:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions
我正在试验 nameof
泛型。我没有得到预期的结果。我不确定这是否是规范的一部分。
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ($"Hello { nameof(FooBar<string>)! }");
}
}
class FooBar<T> { }
我得到的输出是
Hello FooBar!
我希望获得有关类型参数的一些详细信息。
我尝试了一种方法,但由于编译器错误而失败:
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ($"Hello { nameof(Do<string>) }");
}
public static T Do<T>() {}
}
Error CS8084: An argument to nameof operator cannot be method group with type arguments (CS8084) (foo)
这是因为 nameof
是一个编译时构造,而泛型是在运行时初始化的类型吗?还是有其他限制?
I would expect some details about the type parameters
来自设计文档:
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.
由于标准标识符转换(C# 规范中的第 2.4.2 节)不允许 <>
作为有效标识符,因此删除了 <T>
参数。首先删除任何前导 @,然后转换 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 代码库中清楚地看到:
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));
}
有关完整规范,请参阅:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions