2008-10-20 13 views
29

jestem ciekaw, dlaczego niejawna obsada nie w ...W języku C# Dlaczego nie można operator warunkowy niejawnie oddanych do wartości pustych typu

int? someValue = SomeCondition ? ResultOfSomeCalc() : null; 

i dlaczego muszę wykonywać wyraźne obsady zamiast

int? someValue = SomeCondition ? ResultofSomeCalc() : (int?)null; 

Wydaje mi się, że kompilator ma wszystkie informacje potrzebne do podjęcia domyślnej decyzji o podjęciu, czyż nie?

+5

Nie będę sam edytować tytułu, ale proponuję zmienić słowo terrnary na warunkowe - operator nazywa się operatorem warunkowym. Jest to * trójskładnikowy operator - i obecnie jedyny - ale to nie opisuje niczego poza liczbą operandów. –

+3

Może jestem bardziej bezczelny, ale będę ... –

+0

@MarcGravell Jestem bezczelny i mam nadzieję, że poprawny - czy tytuł nie powinien brzmieć '** the ** conditional operator'? :) –

Odpowiedz

27

odpowiedniej części spec C# 3.0 jest 7,13, operator warunkowego:

drugi i trzeci argumenty z: kontrolą operatora od typu ekspresji warunkowej. Niech X i Y będą typami drugiego i trzeciego argumentu. Następnie, jeśli X i Y są tego samego typu, to jest to typ warunkowy. W przeciwnym razie, jeśli niejawna konwersja (§ 6.1) istnieje od X do Y, ale nie od Y do X, to Y jest typ warunkowego wyrażenia. W przeciwnym razie, jeśli niejawna konwersja (§ 6.1) istnieje od Y do X, ale nie od X do Y, wówczas X jest typem wyrażenia warunkowego. W przeciwnym razie nie można określić typu wyrażenia i wystąpi błąd podczas kompilacji.

+6

Podsumowując, nie bierze pod uwagę rodzaju, do którego przypisujesz w wynik operacji. Po prostu próbuje znaleźć właściwą stronę typu równania - z ignorancją typów nullabalnych. – TheSoftwareJedi

+0

Ale weźmy pod uwagę przypadek łańcuchowania trójskładnikowego. Jak inaczej by to wiedział? –

+0

@DJ Floetic: zacznie od "najgłębszego"? Operatora, znajdź typ tego wyniku, a następnie wyjdź z niego. –

14

Jestem również zirytowany, że nie może wywnioskować typu na podstawie przypisania, zwłaszcza gdy jest to typ wartości. Istnieją jednak powody, gdy dochodzi się do dziedziczenia obiektów.

Jeśli "ResultOfSomeCalc()" zwróciło "int?", To będzie działać. C# musi określić typ, niezależnie od tego, co znajduje się po lewej stronie przypisania. Mówisz więc, że zwrócisz wartość null lub int - a logika w kompilatorze nie istnieje, aby zastąpić ją Nullable jako wspólny mianownik.

Zauważ, że te warianty działają, i to może pomóc zrozumieć:

object someValue = true ? new Nullable<int>(ResultOfSomeCalc()) : null; 

object someValue = true ? (int?)ResultOfSomeCalc() : null; 

Nadzieja to pomaga.

+0

Również bardzo dobra odpowiedź, zaakceptowałem DJ'a i wznowiłem twoje. –

0

Jeśli funkcja ResultofSomeCalc() zwraca int? to zadziała.

Jeśli funkcja zwraca int, następnie kompilator emituje ostrzeżenie: Rodzaj wyrażenia warunkowego nie może być ustalona, ​​ponieważ nie istnieje niejawna konwersja między „int” i „”
Zgaduję, że to, co widzisz . Oba wyrażenia w warunkowym operatorze "?:" Muszą mieć ten sam typ lub muszą być przekształcalne do tego samego typu przez niejawną rzutowanie.

Zmień typ zwracanego wyniku ResultOfSomeCalc na int? Lub musisz mieć rzutowanie na wyrażenie zerowe.

5

Wygląda na to, że kompilator powinien być w stanie sam się zorientować, ale jest jeszcze jeden sposób, aby to zrobić, używając domyślnego słowa kluczowego. To może być najmniejszy nieco mniej niż brzydki obsadzie:

int? someValue = SomeCondition ? ResultofSomeCalc() : default(int?); 

Takie wykorzystanie domyślnie nie wydaje się być dobrze udokumentowane, ale to nie działa.Przynajmniej uniemożliwia to zaśmiecanie kodu wartościami magicznymi (twierdzę, że wartości null/zero/false/etc są rzeczywiście wartościami magicznymi).

0

Wykonaj swoją funkcję Typ powrotu ResultOfSomeCalc() jako nullabel int like (int?)
int? someValue = (int?) SomeCondition? ResultofSomeCalc(): (int?) Null;

Powiązane problemy