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é. 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 .
Conversion d’expressions conditionnelles
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 vers ce type
nous définissons une nouvelle conversion d’expression conditionnelle implicite qui permet une conversion implicite de l’expression conditionnelle vers n’importe quel type T
pour lequel il existe une conversion d’expression de e1
en T
et de e2
à T
. Il s’agit d’une erreur si une expression conditionnelle n’a pas de type commun entre e1
et e2
et n’est pas soumise à une conversion d’expression conditionnelle .
Meilleure conversion à partir de l'expression
Nous changeons
Meilleure conversion à partir d’une 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 d’une expression
Étant donné une conversion implicite
C1
qui convertit une expressionE
en un typeT1
, et une conversion impliciteC2
qui convertit une expressionE
en un typeT2
,C1
est une conversion meilleure queC2
siE
ne correspond pas exactement àT2
et si au moins l'une des conditions suivantes est remplie :
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
vers 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, il n’est pas tout à fait identique à 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);
Cela devient ambigu, car la conversion en long
est meilleure pour le premier argument (car elle n’utilise pas la conversion d’expression conditionnelle ), mais la conversion en short
est meilleure pour le deuxième argument (car short
est un 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
vers short
, et nous voulons conserver la signification actuelle du langage de ce programme. La modification serait inobservable au moment de l’exécution, mais avec le programme suivant, la modification serait observable :
_ = (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
vers 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