Target-Typed Podmíněný výraz
Poznámka
Tento článek je specifikace funkce. Specifikace slouží jako návrhový dokument pro funkci. Zahrnuje navrhované změny specifikace spolu s informacemi potřebnými při návrhu a vývoji funkce. Tyto články se publikují, dokud nebudou navrhované změny specifikace finalizovány a začleněny do aktuální specifikace ECMA.
Mezi specifikací funkce a dokončenou implementací může docházet k nějakým nesrovnalostem. Tyto rozdíly jsou zachyceny v příslušných poznámkách ze schůzky návrhu jazyka (LDM) .
Další informace o procesu přijetí specifikací funkcí do jazyka C# najdete v článku o specifikacích .
Problém šampiona: https://github.com/dotnet/csharplang/issues/2460
Převod podmíněného výrazu
Pro podmíněný výraz c ? e1 : e2
, kdy
- neexistuje žádný společný typ pro
e1
ae2
, nebo - pro který existuje běžný typ, ale jeden z výrazů
e1
neboe2
nemá žádný implicitní převod na tento typ.
definujeme nový implicitní převod podmíněného výrazu, který umožňuje implicitní převod z podmíněného výrazu na libovolný typ T
, pro který existuje převod z výrazu z e1
na T
a také z e2
na T
. Jedná se o chybu, pokud podmíněný výraz nemá společný typ mezi e1
a e2
ani není předmětem převodu podmíněného výrazu .
Lepší převod z výrazu
Změníme
Lepší převod z výrazu
Vzhledem k implicitnímu převodu
C1
, který převádí z výrazuE
na typT1
, a k implicitnímu převoduC2
, který převádí z výrazuE
na typT2
, jeC1
lepší převod nežC2
, pokudE
přesně neodpovídáT2
a platí alespoň jedna z následujících podmínek:
k
Lepší převod z výrazu
Vzhledem k implicitnímu převodu
C1
, který převádí z výrazuE
na typT1
, a k implicitnímu převoduC2
, který převádí z výrazuE
na typT2
, jeC1
lepší převod nežC2
, pokudE
přesně neodpovídáT2
a platí alespoň jedna z následujících podmínek:
Výraz pro přetypování
Aktuální specifikace jazyka C# říká:
cast_expression ve formě
(T)E
, kdeT
je typ aE
je unary_expression, provádí explicitní převod (§10.3) hodnotyE
na typT
.
V přítomnosti převodu podmíněného výrazu může existovat více než jeden možný převod z E
do T
. S přidáním převodu podmíněného výrazupreferujeme jakýkoli jiný převod na převod podmíněného výrazua používáme převod podmíněného výrazu pouze jako poslední možnost.
Poznámky k návrhu
Důvodem změny na Lepší převod z výrazu je použití případu, jako je tento:
M(b ? 1 : 2);
void M(short);
void M(long);
Tento přístup má dvě malé nevýhody. Zaprvé, není to úplně totéž jako výraz switch:
M(b ? 1 : 2); // calls M(long)
M(b switch { true => 1, false => 2 }); // calls M(short)
Jedná se o stále zásadní změnu, ale její rozsah je méně pravděpodobné, že ovlivní skutečné programy:
M(b ? 1 : 2, 1); // calls M(long, long) without this feature; ambiguous with this feature.
M(short, short);
M(long, long);
To se stává nejednoznačným, protože převod na long
je pro první argument lepší (protože nepoužívá převod podmíněného výrazu ), ale převod na short
je lepší pro druhý argument (protože short
je lepší cíl převodu než long
). Tato zásadní změna se zdá méně závažná, protože nemění nepozorovaně chování existujícího programu.
Důvodem poznámek k výrazu přetypování je zpracování případů, jako je tento:
_ = (short)(b ? 1 : 2);
Tento program v současné době používá explicitní převod z int
na short
a chceme zachovat současný jazykový význam tohoto programu. Změna by během běhu programu byla nepozorovatelná, ale s následujícím programem by změna byla pozorovatelná.
_ = (A)(b ? c : d);
kde c
je typu C
, d
je typu D
a existuje implicitní uživatelsky definovaný převod z C
na D
a implicitní převod definovaný uživatelem z D
na A
a implicitní uživatelem definovaný převod z C
na A
. Pokud je tento kód zkompilován před C# 9.0 a když je b
pravdivé, převedeme z c
na D
a pak na A
. Pokud použijeme převod podmíněného výrazu, pak když je b
pravdivý, převedeme z c
přímo na A
, což spustí jinou posloupnost uživatelského kódu. Proto zacházíme s převodem podmíněného výrazu jako poslední možnost přetypování, abychom zachovali stávající chování.
C# feature specifications