Partager via


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

  1. il n’existe aucun type commun pour e1 et e2, ou
  2. pour laquelle un type commun existe, mais l’une des expressions e1 ou e2 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 expression E en un type T1, et une conversion implicite C2 qui convertit d’une expression E en un type T2, C1 est une meilleure conversion que C2 si E ne correspond pas exactement T2 et au moins l’une des conditions suivantes :

  • E correspond exactement à T1 (§12.6.4.5)
  • T1 est une meilleure cible de conversion que T2 (§12.6.4.7)

à

Meilleure conversion à partir d’une expression

Étant donné une conversion implicite C1 qui convertit une expression E en un type T1, et une conversion implicite C2 qui convertit une expression E en un type T2, C1 est une conversion meilleure que C2 si E 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 et C2 est une conversion d’expression conditionnelle .
  • T1est une meilleure cible de conversion que T2 (§12.6.4.7) et soit C1 et C2 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 et Eune unary_expression, effectue une conversion explicite (§10.3) de la valeur de E vers le type T.

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);

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.