generics的名字

我正在尝试使用generics的名称。 我没有得到我期待的结果。 我不确定这是否属于规范的一部分。

 class MainClass { public static void Main (string[] args) { Console.WriteLine ($"Hello { nameof(FooBar)! }"); } } class FooBar { } 

我得到的输出是

你好FooBar!

我希望有关类型参数的一些细节。

我用一个方法尝试了它,但由于编译错误而失败:

 class MainClass { public static void Main (string[] args) { Console.WriteLine ($"Hello { nameof(Do) }"); } public static T Do() {} } 

错误CS8084:nameof运算符的参数不能是带有类型参数的方法组(CS8084)(foo)

这是因为nameof是一个编译时构造,而generics是在运行时初始化的类型吗? 还是有其他限制?

我希望有关类型参数的一些细节

“规范”说 :

名称的结果。 nameof的结果取决于其参数绑定的符号:

一个或多个成员:如果所有成员具有相同的元数据名称,则nameof的结果是该名称; 否则它是一个错误“这个参数指的是具有不同名称的多个元素”。 在应用标准标识符转换之后 ,成员I or I `的元数据名称仅为“I”。

由于标准标识符转换(C#规范中的第2.4.2节), 参数被删除,该参数不允许<>作为有效标识符。 首先删除任何前导@,然后转换Unicode转义序列,然后删除任何格式化字符。 这当然仍然发生在编译时。 当您尝试打印generics类型的名称时,也可以看到此信息:

 typeof(List).Name; 

将导致:

 List`1 

这是因为nameof是一个编译时构造,而generics是在运行时初始化的类型吗? 还是有其他限制?

第二个错误被设计为无效,以避免名称中的重载解决并发症:

允许generics类型参数? 在命名类型时可能是“是”,因为表达式绑定已经起作用。 大概是’不’。 在命名方法组时,因为在重载解析期间使用/推断了类型参数,并且在名称中必须处理它也会令人困惑。

我们可以在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)); }