Expression conditionnelle de type cible
Remarque
Cet article est une spécification de fonctionnalité. La spécification sert de document de conception pour la fonctionnalité. Elle inclut les changements de spécification proposés, ainsi que les informations nécessaires à la conception et au développement de la fonctionnalité. Ces articles sont publiés jusqu'à ce que les changements proposés soient finalisés et incorporés dans la spécification ECMA actuelle.
Il peut y avoir des différences entre la spécification de la fonctionnalité et l'implémentation réalisée. Ces différences sont consignées dans les notes pertinentes de la réunion de conception linguistique (LDM).
Pour en savoir plus sur le processus d'adoption des speclets de fonctionnalité dans la norme du langage C#, consultez l'article sur les spécifications.
Problème de champion : https://github.com/dotnet/csharplang/issues/2460
Conversion d’une expression conditionnelle
Pour une expression conditionnelle c ? e1 : e2
, quand
- il n’existe aucun type commun pour
e1
ete2
, ou - pour laquelle un type commun existe, mais l’une des expressions
e1
oue2
n’a pas de conversion implicite en ce type
nous définissons une nouvelle conversion d’expression conditionnelle implicite qui permet une conversion implicite de l’expression conditionnelle en n’importe quel type T
pour lequel il existe une conversion à partir de l’expression de e1
en T
et aussi de e2
en T
. Si une expression conditionnelle n’a pas de type commun entre e1
et e2
et n’est pas soumise à une conversion d’expression conditionnelle, il s’agit d’une erreur.
Meilleure conversion à partir de l'expression
Nous changeons
Meilleure conversion à partir de l’expression
Étant donné une conversion implicite
C1
qui convertit d’une expressionE
en un typeT1
, et une conversion impliciteC2
qui convertit d’une expressionE
en un typeT2
,C1
est une meilleure conversion queC2
siE
ne correspond pas exactementT2
et au moins l’une des conditions suivantes :
à
Meilleure conversion à partir de l’expression
Étant donné une conversion implicite
C1
qui convertit d’une expressionE
en un typeT1
, et une conversion impliciteC2
qui convertit d’une expressionE
en un typeT2
,C1
est une meilleure conversion queC2
siE
ne correspond pas exactementT2
et au moins l’une des conditions suivantes :
E
correspond exactement àT1
(§12.6.4.5)C1
n’est pas une conversion d’expression conditionnelle etC2
est une conversion d’expression conditionnelle.T1
est une meilleure cible de conversion queT2
(§12.6.4.7) et soitC1
etC2
sont toutes deux des conversions d'expressions conditionnelles, soit aucune n'est une conversion d'expression conditionnelle.
Expression coulée
La spécification actuelle du langage C# indique
Une cast_expression de la forme
(T)E
, oùT
est un type etE
une unary_expression, effectue une conversion explicite (§10.3) de la valeur deE
vers le typeT
.
En présence de la conversion d’expression conditionnelle, il peut y avoir plusieurs conversions possibles de E
en T
. Avec l’ajout de la conversion d'expression conditionnelle , nous préférons une autre conversion à une conversion d'expression conditionnelle , et utilisons la conversion d'expression conditionnelle uniquement en dernier recours.
Notes de conception
La raison du changement pour une meilleure conversion à partir d'une expression est de traiter un cas comme celui-ci :
M(b ? 1 : 2);
void M(short);
void M(long);
Cette approche présente deux petits inconvénients. Tout d’abord, ce n’est pas tout à fait la même chose que l’expression switch :
M(b ? 1 : 2); // calls M(long)
M(b switch { true => 1, false => 2 }); // calls M(short)
Il s’agit toujours d’un changement cassant, mais son étendue est moins susceptible d’affecter les programmes réels :
M(b ? 1 : 2, 1); // calls M(long, long) without this feature; ambiguous with this feature.
M(short, short);
M(long, long);
Il y a ambiguïté, car la conversion en long
est meilleure pour le premier argument (parce qu’elle n’utilise pas la conversion d’expression conditionnelle), mais la conversion en short
est meilleure pour le deuxième argument (parce que short
est une meilleure cible de conversion que long
). Ce changement de rupture semble moins préoccupant, car il ne modifie pas silencieusement le comportement d’un programme existant.
La raison des notes sur l'expression cast est de traiter un cas comme celui-ci :
_ = (short)(b ? 1 : 2);
Ce programme utilise actuellement la conversion explicite de int
en short
, et nous voulons conserver la signification actuelle du langage de ce programme. Le changement ne serait pas observable au moment de l’exécution, mais avec le programme suivant, il le serait :
_ = (A)(b ? c : d);
où c
est de type C
, d
est de type D
, et il existe une conversion implicite définie par l’utilisateur de C
en D
, et une conversion implicite définie par l’utilisateur de D
en A
, et une conversion implicite définie par l’utilisateur de C
en A
. Si ce code est compilé avant C# 9.0, lorsque b
est vrai, nous convertissons de c
en D
puis en A
. Si nous utilisons la conversion d'expression conditionnelle , alors, lorsque b
est vrai, nous convertissons directement de c
à A
, ce qui exécute une séquence différente de code utilisateur. Par conséquent, nous traitons la conversion d'expression conditionnelle en dernier recours dans un cast, afin de préserver le comportement existant.
C# feature specifications