wyrażenie warunkowe Target-Typed
Notatka
Ten artykuł jest specyfikacją funkcji. Specyfikacja służy jako dokument projektowy dla funkcji. Zawiera proponowane zmiany specyfikacji wraz z informacjami wymaganymi podczas projektowania i opracowywania funkcji. Te artykuły są publikowane do momentu sfinalizowania proponowanych zmian specyfikacji i włączenia ich do obecnej specyfikacji ECMA.
Mogą wystąpić pewne rozbieżności między specyfikacją funkcji a ukończoną implementacją. Te różnice są odnotowane w odpowiednich notatkach ze spotkania dotyczącego projektowania języka (LDM) .
Więcej informacji na temat procesu wdrażania specyfikacji funkcji można znaleźć w standardzie języka C# w artykule dotyczącym specyfikacji .
Konwersja wyrażeń warunkowych
W przypadku wyrażenia warunkowego c ? e1 : e2
, kiedy
- nie ma typowego typu dla
e1
ie2
, lub - dla którego typ wspólny istnieje, ale jedno z wyrażeń
e1
lube2
nie ma niejawnej konwersji na ten typ
Definiujemy nową niejawną konwersję wyrażenia warunkowego , która pozwala na konwersję z wyrażenia warunkowego na dowolny typ T
, dla którego istnieje konwersja z wyrażenia z e1
do T
oraz z e2
do T
. Jest to błąd, gdy wyrażenie warunkowe nie ma wspólnego typu między e1
a e2
ani nie jest poddane konwersji wyrażenia warunkowego .
Lepsza konwersja z wyrażenia
Zmieniamy
Lepsza konwersja z wyrażenia
Biorąc pod uwagę niejawną konwersję
C1
, która konwertuje wyrażenieE
na typT1
, oraz niejawną konwersjęC2
, która konwertuje wyrażenieE
na typT2
,C1
jest lepszą konwersją niżC2
, jeśliE
nie dokładnie odpowiadaT2
i co najmniej jedna z następujących zaszłości zachodzi:
do
Lepsza konwersja wyrażenia
Biorąc pod uwagę niejawną konwersję
C1
, która konwertuje z wyrażeniaE
na typT1
, i niejawną konwersjęC2
, która konwertuje z wyrażeniaE
na typT2
,C1
jest lepszą konwersją niżC2
, jeśliE
nie jest dokładnie zgodna zT2
i co najmniej jedna z następujących zachodzi:
Wyrażenie rzutu
Bieżąca specyfikacja języka C# mówi
cast_expression formularza
(T)E
, gdzieT
jest typem iE
jest unary_expression, wykonuje jawną konwersję (§10.3) wartościE
do typuT
.
W obecności konwersji wyrażenia warunkowego może istnieć więcej niż jedna możliwa konwersja z E
na T
. Po dodaniu konwersji wyrażenia warunkowego , preferujemy każdą inną konwersję niż konwersję wyrażenia warunkowego i używamy konwersji wyrażenia warunkowego tylko w ostateczności.
Uwagi dotyczące projektu
Przyczyną zmiany na Lepsza konwersja wyrażenia jest obsługa przypadku takiego jak:
M(b ? 1 : 2);
void M(short);
void M(long);
Takie podejście ma dwa małe wady. Po pierwsze nie jest to samo co wyrażenie przełącznika:
M(b ? 1 : 2); // calls M(long)
M(b switch { true => 1, false => 2 }); // calls M(short)
Jest to nadal zmiana przełomowa, ale jej zakres jest mniej prawdopodobny, aby wpłynąć na rzeczywiste programy.
M(b ? 1 : 2, 1); // calls M(long, long) without this feature; ambiguous with this feature.
M(short, short);
M(long, long);
Staje się to niejednoznaczne, ponieważ konwersja na long
jest lepsza dla pierwszego argumentu (ponieważ nie używa konwersji wyrażenia warunkowego), ale konwersja na short
jest lepsza dla drugiego argumentu (ponieważ short
jest lepszym celem konwersji niż long
). Ta zmiana powodująca niezgodność wydaje się mniej poważna, ponieważ nie zmienia ona niepostrzeżenie zachowania istniejącego programu.
Przyczyną notatek w wyrażeniu rzutowania jest obsługa takiego przypadku:
_ = (short)(b ? 1 : 2);
Ten program używa obecnie jawnej konwersji z int
do short
i chcemy zachować bieżące znaczenie języka tego programu. Zmiana byłaby nieobserwowalna w czasie wykonywania, ale w przypadku następującego programu zmiana byłaby zauważalna:
_ = (A)(b ? c : d);
gdzie c
jest typu C
, d
jest typu D
, i istnieje niejawna konwersja zdefiniowana przez użytkownika z C
na D
, a niejawna konwersja zdefiniowana przez użytkownika z D
na A
i niejawna konwersja zdefiniowana przez użytkownika z C
na A
. Jeśli ten kod jest kompilowany przed C# 9.0, gdy b
ma wartość true, przekonwertujemy z c
na D
, a następnie na A
. Jeśli używamy konwersji wyrażenia warunkowego , to gdy b
jest prawdziwe, dokonujemy bezpośredniej konwersji z c
na A
, co powoduje wykonanie innej sekwencji kodu użytkownika. W związku z tym traktujemy konwersję wyrażenia warunkowego jako ostateczne rozwiązanie w przypadku rzutowania, aby zachować istniejące zachowanie.
C# feature specifications