Sdílet prostřednictvím


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

  1. neexistuje žádný společný typ pro e1 a e2, nebo
  2. pro který existuje běžný typ, ale jeden z výrazů e1 nebo e2 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ýrazu E na typ T1, a k implicitnímu převodu C2, který převádí z výrazu E na typ T2, je C1lepší převod než C2, pokud E 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ýrazu E na typ T1, a k implicitnímu převodu C2, který převádí z výrazu E na typ T2, je C1lepší převod než C2, pokud E přesně neodpovídá T2 a platí alespoň jedna z následujících podmínek:

  • E přesně odpovídá T1 (§12.6.4.5)
  • C1 není převod podmíněného výrazu a C2 je převod podmíněného výrazu.
  • T1 je lepší cíl převodu než T2 (§12.6.4.7) a buď C1 a C2 jsou oba převody podmíněného výrazu, nebo ani jeden není převodem podmíněného výrazu.

Výraz pro přetypování

Aktuální specifikace jazyka C# říká:

cast_expression ve formě (T)E, kde T je typ a E je unary_expression, provádí explicitní převod (§10.3) hodnoty E na typ T.

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 shorta 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 Da existuje implicitní uživatelsky definovaný převod z C na Da implicitní převod definovaný uživatelem z D na Aa 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í.