Delen via


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

  1. er is geen algemeen type voor e1 en e2, of
  2. waarvoor een gemeenschappelijk type bestaat, maar een van de expressies e1 of e2 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 Tbestaat. 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 expressie E naar een type T1en een impliciete conversie C2 die wordt geconverteerd van een expressie E naar een type T2, is C1 een betere conversie dan C2 als E niet exact overeenkomt met T2 en ten minste een van de volgende bewaringen:

Naar

Betere conversie van uitdrukking

Gezien een impliciete conversie C1 die wordt geconverteerd van een expressie E naar een type T1en een impliciete conversie C2 die wordt geconverteerd van een expressie E naar een type T2, is C1 een betere conversie dan C2 als E niet exact overeenkomt met T2 en ten minste een van de volgende bewaringen:

  • E komt exact overeen met T1 (§12.6.4.5)
  • C1 is geen conversie van voorwaardelijke expressies en C2 is een conversie van voorwaardelijke expressies.
  • T1 is een beter conversiedoel dan T2 (§12.6.4.7) en C1 en C2 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, waarbij T een type is en E is een unary_expression, voert een expliciete conversie uit (§10.3) van de waarde van E naar type T.

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 shorten 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 Cis, d van het type Dis 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 Aen 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.