Dlaczego to się nie kompiluje?
int? number = true ? 5 : null;
Nie można określić typu wyrażenia warunkowego, ponieważ nie ma niejawnej konwersji między „int” i <null>
Dlaczego to się nie kompiluje?
int? number = true ? 5 : null;
Nie można określić typu wyrażenia warunkowego, ponieważ nie ma niejawnej konwersji między „int” i <null>
Odpowiedzi:
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
xiyma typ, a obaxiysą 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 null nadal 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 typXiyma typYto
Jeśli niejawna konwersja (§6.1) istnieje od
XdoY, ale nie odYdoX, toYjest to typ wyrażenia warunkowego.Jeśli niejawna konwersja (§6.1) istnieje od
YdoX, ale nie odXdoY, toXjest 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ń.
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:
int? number = true ? 5 : (int?)null;
int? number = true ? 5 : null as int?;
int? number = true ? 5 : (int?)null;i int? number = true ? (int?)5 : null;oba kompilują !! Scratch, scratch
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 : new int?();
int? num = true ? 5 : null as int?;
int? num = true ? 5 : (int?)null;
int? num = true ? (int?)5 : null;
int? num = true ? 5 as int? : null;
int? num = true ? new int?(5) : null;
Ponadto, gdziekolwiek zobaczysz int?, możesz również użyć Nullable<int>.
W C# 9tym jest teraz dozwolone blogowanie
Wpisano cel ?? i ?
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 type
int? result = b ? 0 : null; // nullable value type
Albo twój przykład:
// Allowed in C# 9.
int? number = true ? 5 : null;