Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

229
Vistas
¿Por qué no se puede usar nameof con tipos calificados de alias en el nivel raíz?

Imagine un tipo en el nivel del espacio de nombres raíz (podría estar en el espacio global predeterminado o podría ser un extern alias ).

Parece que no se puede hacer referencia a este tipo a través de nameof() , cuando se usa el prefijo de alias. Funciona bien con typeof y mediante el using alias (aunque nameof en un alias de using produce el nombre del alias, no el nombre del tipo). El compilador objeta CS8083, "Un nombre calificado con alias no es una expresión".

Pero: ¿hay alguna razón para esto? ¿Esto está tratando de prevenir algún escenario de problema oscuro? o cumplir con algunos minutos de especificación? ¿O es quizás un error del compilador? También me complace señalar que, por lo general , no deberíamos declarar tipos en la raíz del espacio de nombres: CA1050 tiene mucha razón al respecto; pero ese no es el punto aquí :)

A continuación se muestra un ejemplo completo; tenga en cuenta que en este ejemplo se usan dos proyectos para using la verificación de alias, pero para simplificar, todo lo que involucre a C puede ignorarse para una investigación simple.

 extern alias foo; using System; using X = global::A; using Y = global::FunWithNamespaces.B; using Z = foo::C; public class A { } namespace FunWithNamespaces { public class B { } public class Program { static void Main() { // oddness is on the lines marked ## CS8083 // relative-qualified using typeof Console.WriteLine(typeof(X).Name); // A, expected Console.WriteLine(typeof(Y).Name); // B, expected Console.WriteLine(typeof(Z).Name); // C, expected Console.WriteLine(typeof(A).Name); // A Console.WriteLine(typeof(B).Name); // B // note: can't talk about C without using an alias qualifier or a using-alias Console.WriteLine(typeof(Console).Name); // Console // relative-qualified things using nameof Console.WriteLine(nameof(X)); // X; I'm on the fence about X vs A, but... whatever Console.WriteLine(nameof(Y)); // Y; I'm on the fence about Y vs B, but... whatever Console.WriteLine(nameof(Z)); // Z; I'm on the fence about Z vs C, but... whatever Console.WriteLine(nameof(A)); // A Console.WriteLine(nameof(B)); // B // note: can't talk about C without using an alias qualifier or a using-alias Console.WriteLine(nameof(Console)); // Console // alias-qualified things using typeof Console.WriteLine(typeof(global::A).Name); // A Console.WriteLine(typeof(global::FunWithNamespaces.B).Name); // B Console.WriteLine(typeof(foo::C).Name); // C Console.WriteLine(typeof(global::System.Console).Name); // Console // alias-qualified things using nameof // ??? Console.WriteLine(nameof(global::A)); // ## CS8083 An alias-qualified name is not an expression Console.WriteLine(nameof(global::FunWithNamespaces.B)); // B // ??? Console.WriteLine(nameof(foo::C)); // ## CS8083 An alias-qualified name is not an expression Console.WriteLine(nameof(global::System.Console)); // Console } } }

donde C se define en un ensamblado separado y se hace referencia con alias especificados como foo , y es simplemente:

 public class C { }

Editar: en términos de especificación, esto se reduce a https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#nameof-expressions , donde nameof_expression debe ser un simple_name (que no lo es) o un named_entity_target '.' identifier type_argument_list? - entonces: para todos los casos que no son un nombre simple, debe haber un .something - pero supongo que la pregunta subyacente aquí es ¿por qué debe haber un .something , frente a alguna otra construcción que permita global::Foo ? Por ejemplo:

 nameof_expression : 'nameof' '(' named_entity ')' ; named_entity : simple_name | named_entity_target '.' identifier type_argument_list? | qualified_alias_member type_argument_list? ; named_entity_target : 'this' | 'base' | named_entity | predefined_type | qualified_alias_member ;
over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Respuesta a la pregunta subyacente

si vino aquí por una decisión en tiempo de compilación, no hay forma en este momento. Es un comportamiento esperado del lado del compilador como resultado de la compilación de expresiones.

Solución de ejecución rápida

(typeof(f::SomeCustomClassName)).Name en lugar de nameof(f::SomeCustomClassName)

Explicación

Ahora volvamos a ver nameof_expression (enlace)

 nameof_expression = 'nameof' '(' named_entity ')'

donde está la entidad_nombrada

 named_entity = named_entity_target ('.' identifier type_argument_list?)*

Y echemos un vistazo de nuevo al nombre de la clase de llamada. En la variante común sin alias, tenemos: nameof(SomeCustomClassName) que se despliega a nameof(ConsoleApp1.SomeCustomClassName)

Eso coincide con named_entity_target.identifier .

Pero el alias nameof(f::SomeCustomClassName) ...

De la especificación

 named_entity_target : simple_name | 'this' | 'base' | predefined_type | qualified_alias_member ;

¿Es el miembro_alias_calificado así llamado_objetivo_entidad = miembro_alias_calificado

Entonces nameof_expression se desarrolla en

 qualified_alias_member ('.' identifier type_argument_list?)*

Echemos un vistazo a named_alias_member (enlace) :

 qualified_alias_member : identifier '::' identifier type_argument_list? ;

De acuerdo con todo esto tenemos

 identifier '::' identifier ('.' identifier type_argument_list?)*

Eso no coincide con nameof(f::SomeCustomClassName) Por eso es incorrecto para el compilador. Es por eso que necesita el nombre de punto nameof(f::SomeCustomClassName.SomeCustomClassName2)

no es un error Es un error de cálculo de los creadores de expresiones o una limitación intencional.

over 4 years ago · Santiago Trujillo Denunciar

0

La resolución de la expresión se realiza durante la compilación, de ahí los errores de compilación de CSxxx. Entonces, el operador nameof() no tiene efecto durante el tiempo de ejecución.

Además, podría usar .Net Reflection para obtener el nombre del valor que le diste como parámetro. Por lo tanto, para resolver un tipo a través de la reflexión, el compilador necesita la "ruta completa" del miembro (es decir, desde el espacio de nombres hasta él).

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda