nombre con genéricos


Estaba experimentando con nameof con genéricos. No obtuve el resultado que esperaba. No estoy seguro si esto es parte de la especificación o no.

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

class FooBar<T> { }

La salida que obtengo es

Hola FooBar!

Esperaría algunos detalles sobre los parámetros de tipo.

Lo probé con un método y eso falla con un error del compilador:

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

    public static T Do<T>() {}
}

Error CS8084: Un argumento para el operador nameof no puede ser un grupo de métodos con argumentos de tipo (CS8084) (foo)

¿Es esto porque nameof es una construcción en tiempo de compilación y los genéricos son tipos inicializados en tiempo de ejecución? ¿O hay alguna otra limitación?

Author: Yuval Itzchakov, 2015-04-26

1 answers

Esperaría algunos detalles sobre los parámetros de tipo

El" spec " dice:

Resultado de nameof. El resultado de nameof depende de los símbolos que su argumento ligado a:

Uno o más miembros: si todos los miembros tienen el mismo nombre de metadatos, entonces el resultado de nameof es ese nombre; de lo contrario es un error " Esto argumento se refiere a múltiples elementos con diferentes nombres". El metadatos nombre de un miembro Ior I 'es simplemente" I " después del estándar se han aplicado transformaciones de identificador.

El parámetro <T> se elimina debido a transformaciones de identificador estándar (sección §2.4.2 en la especificación de C#) que no permite <> como identificadores válidos. Primero se elimina cualquier @ inicial, luego se transforman las secuencias de escape Unicode y luego se eliminan los caracteres de formato. Por supuesto, esto todavía sucede en tiempo de compilación. También puedes ver esto cuando intente imprimir el nombre de un tipo genérico:

typeof(List<string>).Name;

Resultará en:

List`1

Es esto porque nameof es una construcción en tiempo de compilación y los genéricos son tipos inicializados en tiempo de ejecución? ¿O hay alguna otra limitación?

El segundo error se especifica como inválido por diseño para evitar complicaciones de resolución de sobrecarga dentro de nameof:

Permitir argumentos de tipo genérico? Presumiblemente 'sí' al nombrar un tipo ya que así es la expresión la encuadernación ya funciona. Y presumiblemente ' no.' al nombrar un método-grupo desde que se utilizan/inferen argumentos de tipo durante la resolución de sobrecarga, y sería confuso también tener que ocúpate de eso en nameof.

Podemos verlo claramente en el código base de 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));
}
 20
Author: Yuval Itzchakov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-01 10:20:28