Compartir vía


Permitir el uso de la directiva alias para hacer referencia a cualquier tipo de tipo

Nota

Este artículo es una especificación de características. La especificación actúa como documento de diseño de la característica. Incluye cambios de especificación propuestos, junto con la información necesaria durante el diseño y el desarrollo de la característica. Estos artículos se publican hasta que se finalizan los cambios de especificación propuestos e se incorporan en la especificación ECMA actual.

Puede haber algunas discrepancias entre la especificación de características y la implementación completada. Esas diferencias se recogen en las notas de la reunión de diseño de lenguaje (LDM) correspondientes.

Puede obtener más información sobre el proceso de adopción de especificaciones de características en el estándar del lenguaje C# en el artículo sobre las especificaciones de .

Problema del campeón: https://github.com/dotnet/csharplang/issues/8645

Resumen

Relajar la directiva using_alias (sección 13.5.2) para permitir que apunte a cualquier tipo, no solo a tipos con nombre. Esto admitiría tipos no permitidos hoy en día, como: tipos de tupla, tipos de puntero, tipos de matriz, etc. Por ejemplo, esto ahora se permitiría:

using Point = (int x, int y);

Motivación

Durante años, C# ha tenido la capacidad de introducir alias para espacios de nombres y tipos con nombre (clases, delegados, interfaces, registros y structs). Esto funcionó de forma aceptable, ya que proporcionó un medio para introducir nombres no conflictivos en los casos en los que un nombre normal extraído de using_directives podría ser ambiguo y permitía proporcionar un nombre más sencillo al tratar con tipos genéricos complejos. Sin embargo, el aumento de símbolos de tipo complejo adicionales en el lenguaje ha provocado un mayor uso en el que los alias serían valiosos, pero actualmente no están permitidos. Por ejemplo, tanto las tuplas como los punteros de función pueden tener a menudo formas textuales regulares grandes y complejas que pueden ser dolorosas de escribir continuamente, y una carga para tratar de leer. Los alias podrían ayudar en estos casos proporcionando un nombre corto y proporcionado por el desarrollador que, a continuación, se puede usar en lugar de esas formas estructurales completas.

Diseño detallado

Cambiaremos la gramática de using_alias_directive por lo tanto:

using_alias_directive
-    : 'using' identifier '=' namespace_or_type_name ';'
+    : 'using' identifier '=' (namespace_name | type) ';'
    ;

Las anotaciones de anulabilidad de tipo de referencia de nivel superior no están permitidas.

Interesantemente, la mayoría del lenguaje de especificación en §13.5.2 no es necesario cambiar. La mayoría del lenguaje en él ya hace referencia a "espacio de nombres o tipo", por ejemplo:

Una directiva using_alias introduce un identificador que sirve como alias para un espacio de nombres o tipo dentro de la unidad de compilación o cuerpo de espacio de nombres inmediatamente adyacente.

Esto sigue siendo cierto, solo que la gramática ahora permite que el "tipo" sea cualquier tipo arbitrario, no el conjunto limitado permitido por namespace_or_type_name anteriormente.

Las secciones que necesitan actualizar son:

- The order in which using_alias_directives are written has no significance, and resolution of the namespace_or_type_name referenced by a using_alias_directive is not affected by the using_alias_directive itself or by other using_directives in the immediately containing compilation unit or namespace body. In other words, the namespace_or_type_name of a using_alias_directive is resolved as if the immediately containing compilation unit or namespace body had no using_directives. A using_alias_directive may however be affected by extern_alias_directives in the immediately containing compilation unit or namespace body. In the example
+ The order in which using_alias_directives are written has no significance, and resolution of the `(namespace_name | type)` referenced by a using_alias_directive is not affected by the using_alias_directive itself or by other using_directives in the immediately containing compilation unit or namespace body. In other words, the `(namespace_name | type)` of a using_alias_directive is resolved as if the immediately containing compilation unit or namespace body had no using_directives. A using_alias_directive may however be affected by extern_alias_directives in the immediately containing compilation unit or namespace body. In the example
- The namespace_name referenced by a using_namespace_directive is resolved in the same way as the namespace_or_type_name referenced by a using_alias_directive. Thus, using_namespace_directives in the same compilation unit or namespace body do not affect each other and can be written in any order.
+ The namespace_name referenced by a using_namespace_directive is resolved in the same way as the namespace_or_type_name referenced by a using_alias_directive. Thus, using_namespace_directives in the same compilation unit or namespace body do not affect each other and can be written in any order.
+ It is illegal for a using alias type to be a nullable reference type.

    1. `using X = string?;` is not legal.
    2. `using X = List<string?>;` is legal.  The alias is to `List<...>` which is itself not a nullable reference type itself, even though it contains one as a type argument.
    3. `using X = int?;` is legal.  This is a nullable *value* type, not a nullable *reference* type.

Soporte de alias a tipos que contienen punteros.

Un nuevo contexto inseguro se añade a través de una palabra clave opcional "unsafe" en la producción using_alias_directive:

using_alias_directive
+    : 'using' 'unsafe'? identifier '=' (namespace_name | type) ';'
    ;
    
using_static_directive
+    : 'using' 'static' 'unsafe'? type_name ';'
    ;

+ 'unsafe' can only be used with an using_alias_directive or using_static_directive, not a using_directive.
+ The 'unsafe' keyword present in a 'using_alias_directive' causes the entire textual extent of the 'type' portion (not the 'namespace_name' portion) to become an unsafe context. 
+ The 'unsafe' keyword present in a 'using_static_directive' causes the entire textual extent of the 'type_name' portion to become an unsafe context.