nameof与泛型 [英] nameof with Generics

查看:323
本文介绍了nameof与泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是用 nameof 尝试用仿制药。我没有得到结果我期待。我不知道这是否是规范的一部分与否。

 类MainClass 
{
公共静态无效的主要(字串[] args)
{
Console.WriteLine($你好{nameof(FooBar的<串GT;)}!);
}
}

类FooBar的< T> {}



我得到的输出



<块引用>

您好FooBar的!




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



我的方法试了一下,失败了编译器错误:

 类MainClass 
{
公共静态无效的主要(字串[] args)
{
Console.WriteLine($你好{nameof(走走LT;串>)});
}

公共静态做T< T>(){}
}




错误CS8084:为nameof符的参数不能与类型参数(CS8084)(富)


$ b方法组
$ b

这是因为 nameof 是一个编译时间结构和泛型类型在运行时初始化?或者是有一些其他的限制?


解决方案

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




该规范说




nameof的结果 nameof的结果取决于符号,它的
参数绑定。于:



一个或多个成员:如果所有成员都具有相同的元数据名称,然后
nameof的结果是该名称;否则它是一个错误这
参数指的是不同名称的多个元素。一个成员的
的元数据名称 I I< A1 ... AK> 是简单的我之后的标准
标识符变换已应用。




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

 的typeof(名单<串>)。名称; 



将导致:

  List`1 




这是因为nameof在编译时构建和泛型是在运行时初始化
类型?或者是有一些其他的限制?




由设计,以避免在<$ C重载并发症无效指定了第二个错误$ C> nameof :




允许泛型类型参数据推测,'是'命名类型
时,因为这是如何表达的结合已经工作。和大概是'不',$ B $命名时,因为类型参数的方法组用于重载决议中/推断
,它会引起混乱b,来还必须在
处理的。nameof




我们可以看出,显然是在罗斯林代码库:

 私人BoundExpression BindNameofOperatorInternal(InvocationExpressionSyntax节点,
DiagnosticBag诊断)
{
CheckFeatureAvailability(node.GetLocation(),MessageID.IDS_FeatureNameof,诊断) ;

VAR参数= node.ArgumentList.Arguments [0] .Expression;
字符串名称=;

//我们通过创建一个NameofBinder粘结剂放宽顶级成员访问表达式实例-VS静电要求。
变种nameofBinder =新NameofBinder(参数,这一点);
VAR boundArgument = nameofBinder.BindExpression(参数,诊断);

如果(boundArgument.HasAnyErrors&安培;!&安培; CheckSyntaxForNameofArgument(参数,出姓名,诊断)及和放大器; boundArgument.Kind == BoundKind.MethodGroup)
{
变种methodGroup =(BoundMethodGroup)boundArgument;
如果(methodGroup.TypeArgumentsOpt.IsDefaultOrEmpty!)
{
//同类型参数方法组不允许
diagnostics.Add(ErrorCode.ERR_NameofMethodGroupWithTypeParameters,argument.Location);
}
,否则
{
nameofBinder.EnsureNameofExpressionSymbols(methodGroup,诊断);
}
}

返回新BoundNameOfOperator(节点,boundArgument,ConstantValue.Create(名称),Compilation.GetSpecialType(SpecialType.System_String));
}


I was experimenting with nameof with generics. I didn't get the result I was expecting. I'm not sure if this is part of the spec or not.

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

class FooBar<T> { }

The output I get is

Hello FooBar!

I would expect some details about the type parameters.

I tried it with a method and that fails with a compiler error:

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)

Is this because nameof is a compile-time construct and generics are types initialized at runtime? Or is there some other limitation?

解决方案

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<A1...AK> is simply "I" after standard identifier transformations have been applied.

The <T> parameter is removed due to standard identifier transformations (section §2.4.2 in the C# specification) which doesn't permit <> as valid identifiers. First any leading @ is removed, then Unicode escape sequences are transformed, and then any formatting-characters are removed. This of course still happens at compile-time. You can also see this when you try to print out the name of a generic type:

typeof(List<string>).Name;

Will result in:

List`1

Is this because nameof is a compile-time construct and generics are types initialized at runtime? Or is there some other limitation?

The second error is specified as invalid by design in order to avoid overload resolution complications inside 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 to also have to deal with that in nameof.

We can see that clearly in the 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));
}

这篇关于nameof与泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆