generics的名字

Dan*_*ite 28 c# generics mono c#-6.0

我正在尝试nameof使用泛型.我没有得到我期待的结果.我不确定这是否属于规范的一部分.

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

class FooBar<T> { }
Run Code Online (Sandbox Code Playgroud)

我得到的输出是

你好FooBar!

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

我用一个方法尝试了它,并且因编译器错误而失败:

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

    public static T Do<T>() {}
}
Run Code Online (Sandbox Code Playgroud)

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

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

Yuv*_*kov 24

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

"规范"说:

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

一个或多个成员:如果所有成员都具有相同的元数据名称,那么nameof的结果就是该名称; 否则它是一个错误"这个参数引用了具有不同名称的多个元素".在应用标准标识符转换之后,成员I I <isA1 ... AK>`的元数据名称仅为"I".or

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

typeof(List<string>).Name;
Run Code Online (Sandbox Code Playgroud)

将导致:

List`1
Run Code Online (Sandbox Code Playgroud)

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

第二个错误被设计为无效,以避免内部的重载解决复杂化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));
}
Run Code Online (Sandbox Code Playgroud)