Target-Typed Expresión Condicional
Nota:
Este artículo es una especificación de características. La especificación actúa como documento de diseño de la característica. Incluye cambios de especificación propuestos, junto con la información necesaria durante el diseño y el desarrollo de la característica. Estos artículos se publican hasta que se finalizan los cambios de especificación propuestos y se incorporan en la especificación ECMA actual.
Puede haber algunas discrepancias entre la especificación de características y la implementación completada. Esas diferencias se recogen en las notas de la reunión de diseño de lenguaje (LDM) correspondientes.
Puede obtener más información sobre el proceso de adopción de especificaciones de características en el estándar del lenguaje C#, en el artículo sobre especificaciones.
Problema planteado por el experto: https://github.com/dotnet/csharplang/issues/2460
Conversión de expresiones condicionales
Para una expresión condicional c ? e1 : e2
, cuando
- no existe un tipo común para
e1
ye2
o - para la que existe un tipo común pero una de las expresiones
e1
oe2
no tiene conversión implícita a ese tipo
definimos una nueva conversión de expresión condicional implícita que permite una conversión implícita de la expresión condicional a cualquier tipo T
para la cual existe una conversión desde la expresión de e1
a T
, así como de e2
a T
. Es un error si una expresión condicional ni tiene un tipo común entre e1
y e2
ni está sujeta a una conversión de expresión condicional.
Mejor conversión a partir de expresión
Cambiamos
Mejor conversión a partir de expresión
Dada una conversión implícita
C1
que convierte de una expresiónE
a un tipoT1
y una conversión implícitaC2
que convierte de una expresiónE
a un tipoT2
,C1
es una mejor conversión queC2
siE
no coincide exactamente conT2
y se cumple al menos una de las siguientes condiciones:
E
coincide exactamente conT1
(Sección 12.6.4.5)T1
es un objetivo de conversión mejor queT2
(Sección 12.6.4.7)
to
Mejor conversión a partir de expresión
Dada una conversión implícita
C1
que convierte de una expresiónE
a un tipoT1
y una conversión implícitaC2
que convierte de una expresiónE
a un tipoT2
,C1
es una mejor conversión queC2
siE
no coincide exactamente conT2
y se cumple al menos una de las siguientes condiciones:
E
coincide exactamente conT1
(Sección 12.6.4.5)C1
no es una conversión de expresión condicional yC2
es una conversión de expresión condicional.T1
es un destino de conversión mejor queT2
(§12.6.4.7) y tantoC1
comoC2
son conversiones de expresión condicional o ninguno es una conversión de expresión condicional.
Expresión de conversión
La especificación actual del lenguaje C# dice
Una cast_expression con el formato
(T)E
, dondeT
es un tipo yE
es una unary_expression, realiza una conversión explícita (§10.3) del valor deE
al tipoT
.
En presencia de la conversión de expresión condicional puede haber más de una posible conversión de E
a T
. Con la adición de la conversión de expresiones condicionales, preferimos cualquier otra conversión a una conversión de expresión condicional y utilizamos la conversión de expresión condicional solo como último recurso.
Notas de diseño
El motivo del cambio a una mejor conversión de la expresión es para manejar un caso como este:
M(b ? 1 : 2);
void M(short);
void M(long);
Este enfoque tiene dos pequeños inconvenientes. En primer lugar, no es exactamente lo mismo que la expresión switch.
M(b ? 1 : 2); // calls M(long)
M(b switch { true => 1, false => 2 }); // calls M(short)
Sigue siendo un cambio de ruptura, pero su alcance es menos probable que afecte a los programas reales:
M(b ? 1 : 2, 1); // calls M(long, long) without this feature; ambiguous with this feature.
M(short, short);
M(long, long);
Esto se vuelve ambiguo porque la conversión a long
es mejor para el primer argumento (porque no utiliza la conversión de expresión condicional), pero la conversión a short
es mejor para el segundo argumento (porque short
es un mejor objetivo de conversión que long
). Este cambio rompedor parece menos grave porque no cambia silenciosamente el comportamiento de un programa existente.
El motivo de las notas de la expresión de conversión es manejar un caso como el siguiente:
_ = (short)(b ? 1 : 2);
Este programa utiliza actualmente la conversión explícita de int
a short
, y queremos preservar el significado lingüístico actual de este programa. El cambio sería inobservable en tiempo de ejecución, pero con el siguiente programa el cambio sería observable:
_ = (A)(b ? c : d);
donde c
es de tipo C
, d
es de tipo D
, y hay una conversión implícita definida por el usuario de C
a D
, y una conversión implícita definida por el usuario de D
a A
, y una conversión implícita definida por el usuario de C
a A
. Si este código se compila antes de C# 9.0, cuando b
es verdadero, convertimos de c
a D
y luego a A
. Si usamos la conversión de expresiones condicionales, entonces, cuando b
es verdadero, convertimos de c
a A
directamente y ejecutamos una secuencia diferente de código de usuario. Por lo tanto, consideramos la conversión de expresión condicional como último recurso al realizar una conversión, para conservar el comportamiento existente.
C# feature specifications