Voorwaardelijke expressie Target-Typed
Notitie
Dit artikel is een functiespecificatie. De specificatie fungeert als het ontwerpdocument voor de functie. Het bevat voorgestelde specificatiewijzigingen, samen met informatie die nodig is tijdens het ontwerp en de ontwikkeling van de functie. Deze artikelen worden gepubliceerd totdat de voorgestelde specificaties zijn voltooid en opgenomen in de huidige ECMA-specificatie.
Er kunnen enkele verschillen zijn tussen de functiespecificatie en de voltooide implementatie. Deze verschillen worden vastgelegd in de relevante notities van de Language Design Meeting (LDM).
Meer informatie over het proces voor het aannemen van functiespeclets in de C#-taalstandaard vindt u in het artikel over de specificaties.
Kampioenprobleem: https://github.com/dotnet/csharplang/issues/2460
Conversie van voorwaardelijke expressie
Voor een voorwaardelijke expressie c ? e1 : e2
, wanneer
- er is geen algemeen type voor
e1
ene2
, of - waarvoor een gemeenschappelijk type bestaat, maar een van de expressies
e1
ofe2
heeft geen impliciete conversie naar dat type
we definiëren een nieuwe impliciete voorwaardelijke expressieconversie die een impliciete conversie van de voorwaardelijke expressie naar elk type T
toestaat waarvoor een conversie-van-expressie van e1
naar T
en ook van e2
naar T
bestaat. Het is een fout als een voorwaardelijke expressie geen gemeenschappelijk type heeft tussen e1
en e2
, noch onderworpen is aan een voorwaardelijke expressieconversie van .
Betere conversie van uitdrukkingen
We veranderen
Betere conversie van uitdrukking
Gezien een impliciete conversie
C1
die wordt geconverteerd van een expressieE
naar een typeT1
en een impliciete conversieC2
die wordt geconverteerd van een expressieE
naar een typeT2
, isC1
een betere conversie danC2
alsE
niet exact overeenkomt metT2
en ten minste een van de volgende bewaringen:
Naar
Betere conversie van uitdrukking
Gezien een impliciete conversie
C1
die wordt geconverteerd van een expressieE
naar een typeT1
en een impliciete conversieC2
die wordt geconverteerd van een expressieE
naar een typeT2
, isC1
een betere conversie danC2
alsE
niet exact overeenkomt metT2
en ten minste een van de volgende bewaringen:
E
komt exact overeen metT1
(§12.6.4.5)C1
is geen conversie van voorwaardelijke expressies enC2
is een conversie van voorwaardelijke expressies.T1
is een beter conversiedoel danT2
(§12.6.4.7) enC1
enC2
beide conversies van voorwaardelijke expressies zijn of geen van beide is een conversie van voorwaardelijke expressie.
Cast-expressie
De huidige C#-taalspecificatie zegt
Een cast_expression in de vorm van
(T)E
, waarbijT
een type is enE
is een unary_expression, voert een expliciete conversie uit (§10.3) van de waarde vanE
naar typeT
.
In aanwezigheid van de voorwaardelijke expressieconversie kan er meer dan één mogelijke conversie zijn van E
naar T
. Met de toevoeging van conversie van voorwaardelijke expressie, geven we de voorkeur aan elke andere conversie naar conversie van voorwaardelijke expressiesen gebruiken we de conversie van voorwaardelijke expressie alleen als laatste redmiddel.
Ontwerpnotities
De reden voor de wijziging naar Better conversion from expression is om een geval als dit af te handelen.
M(b ? 1 : 2);
void M(short);
void M(long);
Deze aanpak heeft twee kleine nadelen. Ten eerste is het niet helemaal hetzelfde als de switchexpressie:
M(b ? 1 : 2); // calls M(long)
M(b switch { true => 1, false => 2 }); // calls M(short)
Dit is nog steeds een belangrijke wijziging, maar het bereik is minder waarschijnlijk van invloed op echte programma's:
M(b ? 1 : 2, 1); // calls M(long, long) without this feature; ambiguous with this feature.
M(short, short);
M(long, long);
Dit wordt dubbelzinnig omdat de conversie naar long
beter is voor het eerste argument (omdat deze niet gebruikmaakt van de conversie van voorwaardelijke expressie), maar de conversie naar short
is beter voor het tweede argument (omdat short
een beter conversiedoel is dan long
). Deze breaking change lijkt minder ernstig omdat het gedrag van een bestaand programma niet stilletjes wordt gewijzigd.
De reden voor de aantekeningen in de cast-expressie is om een geval zoals dit af te handelen.
_ = (short)(b ? 1 : 2);
Dit programma gebruikt momenteel de expliciete conversie van int
naar short
en we willen de huidige taal van dit programma behouden. De wijziging kan tijdens runtime niet worden uitgevoerd, maar met het volgende programma zou de wijziging waarneembaar zijn:
_ = (A)(b ? c : d);
waarbij c
van het type C
is, d
van het type D
is en er een impliciete door de gebruiker gedefinieerde conversie is van C
naar D
, en een impliciete door de gebruiker gedefinieerde conversie van D
naar A
en een impliciete door de gebruiker gedefinieerde conversie van C
naar A
. Als deze code is gecompileerd vóór C# 9.0, converteren we, wanneer b
waar is, van c
naar D
dan naar A
. Als we de conversie toepassen van de voorwaardelijke expressie , en b
is waar, converteren we rechtstreeks van c
naar A
, waarmee een andere reeks gebruikerscode wordt uitgevoerd. Daarom behandelen we de conversie van voorwaardelijke uitdrukking naar een cast als een laatste redmiddel om het bestaande gedrag te behouden.
C# feature specifications