Target-Typed Villkorsuttryck
Not
Den här artikeln är en funktionsspecifikation. Specifikationen fungerar som designdokument för funktionen. Den innehåller föreslagna specifikationsändringar, tillsammans med information som behövs under utformningen och utvecklingen av funktionen. Dessa artiklar publiceras tills de föreslagna specifikationsändringarna har slutförts och införlivats i den aktuella ECMA-specifikationen.
Det kan finnas vissa skillnader mellan funktionsspecifikationen och den slutförda implementeringen. Dessa skillnader dokumenteras i de relevanta LDM-anteckningarna (Language Design Meeting) .
Du kan läsa mer om processen för att införa funktionsspecifikationer i C#-språkstandarden i artikeln om specifikationerna.
Champion-problem: https://github.com/dotnet/csharplang/issues/2460
Konvertering av villkorsuttryck
För ett villkorsuttryck c ? e1 : e2
, när
- det inte finns någon vanlig typ för
e1
oche2
, eller - för vilka en gemensam typ finns men ett av uttrycken
e1
ellere2
inte har någon implicit konvertering till den typen
vi definierar en ny implicit konvertering av villkorsstyrda uttryck som tillåter en implicit konvertering från villkorsuttrycket till alla typer T
där det finns en konvertering från uttryck från e1
till T
och även från e2
till T
. Det är ett fel om ett villkorsuttryck varken har någon gemensam typ mellan e1
och e2
och inte heller är föremål för en konvertering av villkorsuttryck.
Bättre konvertering från uttryck
Vi ändrar
Bättre konvertering från uttryck
Med en implicit konvertering
C1
som konverteras från ett uttryckE
till en typT1
och en implicit konverteringC2
som konverteras från ett uttryckE
till en typT2
ärC1
en bättre konvertering änC2
omE
inte exakt matcharT2
och minst något av följande gäller:
till
Bättre konvertering från uttryck
Med en implicit konvertering
C1
som konverteras från ett uttryckE
till en typT1
och en implicit konverteringC2
som konverteras från ett uttryckE
till en typT2
ärC1
en bättre konvertering änC2
omE
inte exakt matcharT2
och minst något av följande gäller:
Cast-uttryck
Den aktuella C#-språkspecifikationen säger
En cast_expression i formen
(T)E
, därT
är en typ ochE
är en unary_expression, utför en explicit konvertering (§10.3) av värdet förE
till typenT
.
Vid närvaro av villkorsstyrda uttryck kan det finnas fler än en möjlig konvertering från E
till T
. Med tillägg av konvertering av villkorsuttryckföredrar vi alla andra konverteringar till en konvertering av villkorsuttryckoch använder konverteringen villkorsuttryck endast som en sista utväg.
Designanteckningar
Anledningen till ändringen i Bättre konvertering av uttryck är att hantera ett fall som detta:
M(b ? 1 : 2);
void M(short);
void M(long);
Den här metoden har två små nackdelar. För det första är det inte riktigt samma som switchuttrycket:
M(b ? 1 : 2); // calls M(long)
M(b switch { true => 1, false => 2 }); // calls M(short)
Detta är fortfarande en icke-bakåtkompatibel ändring, men omfånget är mindre troligt att det påverkar verkliga program:
M(b ? 1 : 2, 1); // calls M(long, long) without this feature; ambiguous with this feature.
M(short, short);
M(long, long);
Detta blir tvetydigt eftersom konverteringen till long
är bättre för det första argumentet (eftersom den inte använder konvertering av villkorsuttryck), men konverteringen till short
är bättre för det andra argumentet (eftersom short
är ett bättre konverteringsmål än long
). Den här ändringen som bryter mot bakåtkompatibilitet verkar mindre allvarlig eftersom den inte ändrar beteendet hos ett befintligt program utan varning.
Anledningen till anmärkningarna på cast-uttrycket är att hantera ett fall som detta:
_ = (short)(b ? 1 : 2);
Det här programmet använder för närvarande den explicita konverteringen från int
till short
, och vi vill bevara den aktuella språk innebörden av det här programmet. Ändringen skulle inte kunna observeras vid körning, men med följande program skulle ändringen vara observerbar:
_ = (A)(b ? c : d);
där c
är av typen C
, d
är av typen D
och det finns en implicit användardefinierad konvertering från C
till D
och en implicit användardefinierad konvertering från D
till A
och en implicit användardefinierad konvertering från C
till A
. Om den här koden kompileras före C# 9.0 konverterar vi från b
till c
sedan till D
när A
är sant. Om vi använder konverteringen av det villkorsstyrda uttrycket , konverterar vi direkt från b
till c
när A
är sant, vilket resulterar i att en annan sekvens av användarkod körs. Därför behandlar vi konvertering av villkorsuttryck som en sista utväg i en cast för att bevara befintligt beteende.
C# feature specifications