Expressions new
de type cible
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/100
Résumé
Ne nécessite pas de spécification de type pour les constructeurs lorsque le type est connu.
Motivation
Autoriser l’initialisation de champ sans dupliquer le type.
Dictionary<string, List<int>> field = new() {
{ "item1", new() { 1, 2, 3 } }
};
Autorisez l’omission du type lorsqu’il peut être déduit de l’utilisation.
XmlReader.Create(reader, new() { IgnoreWhitespace = true });
Instanciez un objet sans écrire le type.
private readonly static object s_syncObj = new();
Spécification
Une nouvelle forme syntaxique, target_typed_new de la object_creation_expression est acceptée dans laquelle le type est facultatif.
object_creation_expression
: 'new' type '(' argument_list? ')' object_or_collection_initializer?
| 'new' type object_or_collection_initializer
| target_typed_new
;
target_typed_new
: 'new' '(' argument_list? ')' object_or_collection_initializer?
;
Une expression target_typed_new n’a pas de type. Cependant, il existe une object creation conversion qui est une conversion implicite d'une expression, qui existe à partir d'un target_typed_new pour chaque type.
Étant donné un type cible T
, le type T0
est le type sous-jacent de T
si T
est une instance de System.Nullable
. Sinon, T0
est T
. La signification d’une expression target_typed_new convertie en type T
est identique à la signification d’un object_creation_expression correspondant qui spécifie T0
comme type.
Il s’agit d’une erreur au moment de la compilation si un target_typed_new est utilisé comme opérande d’un opérateur unaire ou binaire, ou s’il est utilisé lorsqu’il n’est pas soumis à une conversion de création d’objet .
Problème ouvert : devrions-nous autoriser les délégués et les tuples en tant que type cible ?
Les règles ci-dessus incluent les délégués (un type de référence) et les tuples (un type de structure). Bien que les deux types soient constructibles, si le type est inférable, on peut déjà utiliser une fonction anonyme ou un tuple littéral.
(int a, int b) t = new(1, 2); // "new" is redundant
Action a = new(() => {}); // "new" is redundant
(int a, int b) t = new(); // OK; same as (0, 0)
Action a = new(); // no constructor found
Divers
Voici les conséquences de la spécification :
throw new()
est autorisé (le type cible estSystem.Exception
)- Le type cible
new
n'est pas autorisé avec les opérateurs binaires. - Il n'est pas autorisé lorsqu'il n'y a pas de type à cibler : opérateurs unaires, collection d'un
foreach
, dans unusing
, dans une déconstruction, dans une expressionawait
, en tant que propriété de type anonyme (new { Prop = new() }
), dans une instructionlock
, dans unsizeof
, dans une instructionfixed
, dans un accès membre (new().field
), dans une opération dynamiquement distribuée (someDynamic.Method(new())
), dans une requête LINQ, en tant qu'opérande de l'opérateuris
, en tant qu'opérande gauche de l'opérateur??
, ... - Il n'est pas non plus autorisé en tant que
ref
- Les types de types suivants ne sont pas autorisés en tant que cibles de la conversion
- types d’énumération :
new()
fonctionne (commenew Enum()
fonctionne pour donner la valeur par défaut), maisnew(1)
ne fonctionne pas comme les types d’énumération n’ont pas de constructeur. - types d’interface : Cela fonctionne de la même façon que l’expression de création correspondante pour les types COM.
- Types de tableaux : les tableaux ont besoin d'une syntaxe spéciale pour fournir la longueur.
- dynamique : nous n’autorisons pas
new dynamic()
. Nous n’autorisons donc pasnew()
avecdynamic
comme type cible. - tuples : Ils ont la même signification qu'une création d'objet utilisant le type sous-jacent.
- Tous les autres types qui ne sont pas autorisés dans le object_creation_expression sont également exclus, par exemple, les types de pointeur.
- types d’énumération :
Inconvénients
On s'est inquiété du fait que les types new
cibles créent de nouvelles catégories de ruptures, mais c'est déjà le cas avec null
et default
, et cela n'a pas posé de problème majeur.
Alternatives
La plupart des plaintes concernant les types trop longs à dupliquer dans l'initialisation des champs concernent les arguments de type et non le type lui-même. Nous pourrions déduire uniquement les arguments de type comme new Dictionary(...)
(ou similaire) et déduire les arguments de type localement à partir des arguments ou de l'initialisateur de collection.
Questions
- Devrions-nous interdire les utilisations dans les arborescences d’expressions ? (non)
- Comment la fonctionnalité interagit avec les arguments
dynamic
? (aucun traitement spécial) - Comment IntelliSense doit-il fonctionner avec
new()
? (uniquement lorsqu’il existe un type cible unique)
Concevoir des réunions
C# feature specifications