Partage via


Autoriser l’utilisation d’une directive d’alias pour référencer n’importe quel type de type

Remarque

Cet article est une spécification de fonctionnalité. La spécification sert de document de conception pour la fonctionnalité. Il inclut les modifications de spécification proposées, ainsi que les informations nécessaires pendant la conception et le développement de la fonctionnalité. Ces articles sont publiés jusqu’à ce que les modifications de spécification proposées soient finalisées et incorporées dans la spécification ECMA actuelle.

Il peut y avoir des différences entre la spécification de la fonctionnalité et l’implémentation terminée. Ces différences sont consignées dans les notes pertinentes de la réunion de conception linguistique (LDM).

Vous pouvez en savoir plus sur le processus d’adoption des speclets de fonctionnalités dans la norme de langage C# dans l’article sur les spécifications .

Problème de champion : https://github.com/dotnet/csharplang/issues/8645

Résumé

Assouplissez le using_alias_directive (§13.5.2) pour lui permettre de pointer vers n’importe quel type, pas seulement les types nommés. Cela prend en charge les types non autorisés aujourd’hui, comme les types tuple, les types de pointeur, les types de tableaux, etc. Par exemple, cela serait désormais autorisé :

using Point = (int x, int y);

Motivation

Depuis longtemps, C# a eu la possibilité de créer des alias pour les espaces de noms et les types nommés (classes, délégués, interfaces, enregistrements et structures). Cela a fonctionné de manière acceptable, car il a fourni un moyen d’introduire des noms non conflictuels dans les cas où un nom normal tiré d'using_directives peut être ambigu, et il a permis de fournir un nom plus simple lors de la gestion des types génériques complexes. Toutefois, l’augmentation des symboles de type complexes supplémentaires dans la langue a provoqué une utilisation plus importante où les alias seraient précieux, mais ne sont pas autorisés actuellement. Par exemple, les tuples et les pointeurs de fonction peuvent souvent avoir des formes textuelles régulières volumineuses et complexes, ce qui peut être fastidieux à écrire à chaque fois et rend la lecture difficile. Les alias aideront dans ces cas en donnant un nom court, fourni par le développeur, qui peut ensuite être utilisé à la place de ces formes structurelles complètes.

Conception détaillée

Nous modifierons ainsi la grammaire de using_alias_directive :

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

Les annotations de nullabilité de références de niveau supérieur ne sont pas autorisées.

Il est intéressant de noter que la plupart des langages de spécification dans §13.5.2 n’ont pas besoin de changer. La plupart du langage dans celui-ci fait déjà référence à « espace de noms ou type », par exemple :

Une using_alias_directive introduit un identificateur qui sert d’alias pour un espace de noms ou un type dans l’unité de compilation ou le corps de l’espace de noms directement englobant.

Cela reste vrai, juste que la grammaire permet désormais au « type » d’être n’importe quel type arbitraire, et non l’ensemble limité autorisé par namespace_or_type_name précédemment.

Les sections qui ont besoin de la mise à jour sont les suivantes :

- 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.

Prise en charge des alias pour les types contenant des pointeurs.

Un nouveau contexte non sécurisé est ajouté par le biais d’un mot clé « unsafe » facultatif dans la production 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.