我正在尝试使用泛型nameof
。我没有得到我期待的结果。我不确定这是否属于规范的一部分。
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ($"Hello { nameof(FooBar<string>)! }");
}
}
class FooBar<T> { }
我得到的输出是
你好FooBar!
我希望有关类型参数的一些细节。
我用一个方法尝试了它,并且因编译错误而失败:
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ($"Hello { nameof(Do<string>) }");
}
public static T Do<T>() {}
}
错误CS8084:nameof运算符的参数不能是带有类型参数的方法组(CS8084)(foo)
这是因为nameof
是编译时构造,而泛型是在运行时初始化的类型吗?还是有其他限制吗?
答案 0 :(得分:22)
我希望有关类型参数的一些细节
nameof的结果。 nameof的结果取决于它的符号 参数绑定到:
一个或多个成员:如果所有成员都具有相同的元数据名称 nameof的结果是那个名字;否则是一个错误“这个 参数是指具有不同名称的多个元素“ 成员的元数据名称 I
or
I&lt; isA1 ... AK&gt;`标准后简称为“我” 已应用标识符转换。
由于标准标识符转换(C#规范中的第2.4.2节),<T>
参数被删除,该参数不允许<>
作为有效标识符。首先删除任何前导@,然后转换Unicode转义序列,然后删除任何格式化字符。这当然仍然发生在编译时。当您尝试打印泛型类型的名称时,也可以看到这一点:
typeof(List<string>).Name;
将导致:
List`1
这是因为nameof是一个编译时构造和泛型 在运行时初始化的类型?还是有其他限制吗?
第二个错误被设计为无效,以避免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));
}