Spec (§7.14) mówi, że dla wyrażenia warunkowego b ? x : y, istnieją trzy możliwości, albo xi yobie mają typ i pewne warunki dobre są spełnione, tylko jeden xi yma typ i pewne warunki dobre są spełnione, lub błąd czasu kompilacji występuje. Tutaj „pewne dobre warunki” oznaczają, że możliwe są pewne konwersje, które omówimy szczegółowo poniżej.
Teraz przejdźmy do podstawowej części specyfikacji:
Jeśli tylko jeden z xi yma typ, a oba xi ysą niejawnie konwertowane na ten typ, to jest to typ wyrażenia warunkowego.
Problem w tym, że w
int? number =true?5:null;
tylko jeden z wyników warunkowych ma typ. Tutaj xjest intdosłowne, i yto null, które ma nie mieć typ i nullnie jest niejawnie zamienny do int1 . Dlatego „pewne dobre warunki” nie są spełnione i pojawia się błąd w czasie kompilacji.
Można to obejść na dwa sposoby:
int? number =true?(int?)5:null;
Tutaj nadal jesteśmy w przypadku, gdy tylko jeden z xi yma typ. Należy zauważyć, że nullnadal nie ma typ jeszcze kompilator nie będzie miał żadnego problemu z tego powodu (int?)5i nullto zarówno w sposób dorozumiany do zamienny int?(§6.1.4 i §6.1.5).
Drugi sposób to oczywiście:
int? number =true?5:(int?)null;
ale teraz musimy przeczytać inną klauzulę w specyfikacji, aby zrozumieć, dlaczego jest to w porządku:
Jeśli xma typ Xi yma typ Yto
Jeśli niejawna konwersja (§6.1) istnieje od Xdo Y, ale nie od Ydo X, to Yjest to typ wyrażenia warunkowego.
Jeśli niejawna konwersja (§6.1) istnieje od Ydo X, ale nie od Xdo Y, to Xjest to typ wyrażenia warunkowego.
W przeciwnym razie nie można określić typu wyrażenia i wystąpi błąd w czasie kompilacji.
Tutaj xjest typu inti yjest typu int?. Nie ma niejawna konwersja od int?celu int, ale istnieje niejawna konwersja z intdo int?tak typ wyrażenia jest int?.
1 : Należy ponadto zauważyć, że typ lewej strony jest pomijany przy określaniu typu wyrażenia warunkowego, co jest tutaj częstym źródłem nieporozumień.
Dobre cytowanie specyfikacji, aby zilustrować, dlaczego tak się dzieje - +1!
JerKimball
7
Inną opcją jest new int?()na miejscu (int?)null.
Guvante
1
Dzieje się tak również w przypadku, gdy masz typ pola bazy danych dopuszczający wartość null, na przykład DateTime dopuszczający wartość null, i próbujesz rzutować dane do DateTime, gdy jest to wymagane(DateTime?)
Mike Upjohn
73
null nie ma żadnego rozpoznawalnego typu - wystarczy trochę popchnąć, aby był szczęśliwy:
Problem nie polega na tym, nullże nie ma identyfikowalnego typu. Problem polega na tym, że nie ma niejawnej konwersji z nullna int. Szczegóły tutaj .
jason
interesującą rzeczą jest to, że int? number = true ? 5 : (int?)null;i int? number = true ? (int?)5 : null;oba kompilują !! Scratch, scratch
davidhq
2
I pokryć dokładnie dlaczego tak się dzieje w mojej odpowiedzi .
jason
4
Jak wspominali inni, 5 jest ikoną inti nullnie można jej niejawnie przekonwertować na int.
Oto inne sposoby obejścia tego problemu:
int? num =true?5:default(int?);int? num =true?5:newint?();int? num =true?5:nullasint?;int? num =true?5:(int?)null;int? num =true?(int?)5:null;int? num =true?5asint?:null;int? num =true?newint?(5):null;
Ponadto, gdziekolwiek zobaczysz int?, możesz również użyć Nullable<int>.
Czasami warunkowe? i?: wyrażenia nie mają oczywistego typu współdzielonego między gałęziami. Takie przypadki zawodzą dzisiaj, ale C # 9.0 na to pozwoli, jeśli istnieje typ docelowy, na który obie gałęzie konwertują:
Person person = student ?? customer;// Shared base typeint? result = b ?0:null;// nullable value type
Odpowiedzi:
Spec (§7.14) mówi, że dla wyrażenia warunkowego
b ? x : y
, istnieją trzy możliwości, albox
iy
obie mają typ i pewne warunki dobre są spełnione, tylko jedenx
iy
ma typ i pewne warunki dobre są spełnione, lub błąd czasu kompilacji występuje. Tutaj „pewne dobre warunki” oznaczają, że możliwe są pewne konwersje, które omówimy szczegółowo poniżej.Teraz przejdźmy do podstawowej części specyfikacji:
Problem w tym, że w
tylko jeden z wyników warunkowych ma typ. Tutaj
x
jestint
dosłowne, iy
tonull
, które ma nie mieć typ inull
nie jest niejawnie zamienny doint
1 . Dlatego „pewne dobre warunki” nie są spełnione i pojawia się błąd w czasie kompilacji.Można to obejść na dwa sposoby:
Tutaj nadal jesteśmy w przypadku, gdy tylko jeden z
x
iy
ma typ. Należy zauważyć, żenull
nadal nie ma typ jeszcze kompilator nie będzie miał żadnego problemu z tego powodu(int?)5
inull
to zarówno w sposób dorozumiany do zamiennyint?
(§6.1.4 i §6.1.5).Drugi sposób to oczywiście:
ale teraz musimy przeczytać inną klauzulę w specyfikacji, aby zrozumieć, dlaczego jest to w porządku:
Tutaj
x
jest typuint
iy
jest typuint?
. Nie ma niejawna konwersja odint?
celuint
, ale istnieje niejawna konwersja zint
doint?
tak typ wyrażenia jestint?
.1 : Należy ponadto zauważyć, że typ lewej strony jest pomijany przy określaniu typu wyrażenia warunkowego, co jest tutaj częstym źródłem nieporozumień.
źródło
new int?()
na miejscu(int?)null
.DateTime
, gdy jest to wymagane(DateTime?)
null
nie ma żadnego rozpoznawalnego typu - wystarczy trochę popchnąć, aby był szczęśliwy:źródło
int? number = true ? 5 : null as int?;
null
że nie ma identyfikowalnego typu. Problem polega na tym, że nie ma niejawnej konwersji znull
naint
. Szczegóły tutaj .int? number = true ? 5 : (int?)null;
iint? number = true ? (int?)5 : null;
oba kompilują !! Scratch, scratchJak wspominali inni, 5 jest ikoną
int
inull
nie można jej niejawnie przekonwertować naint
.Oto inne sposoby obejścia tego problemu:
Ponadto, gdziekolwiek zobaczysz
int?
, możesz również użyćNullable<int>
.źródło
W
C# 9
tym jest teraz dozwolone blogowanieAlbo twój przykład:
źródło