13

Korzystanie Casting null doesn't compile jako inspiracji iz komentarzem Eric Lippert za:Dlaczego ta niejawna konwersja z int do uint działa?

który demonstruje interesujący przypadek. "uint x = (int) 0;" będzie powiodła się, nawet jeśli int nie jest domyślnie wymienialne na uint.

Wiemy, że to nie działa, ponieważ object nie można przypisać do string:

string x = (object)null; 

Ale to robi, choć intuicyjnie nie powinien go:

uint x = (int)0; 

Dlaczego czy kompilator pozwala na to przypadek, gdy int nie jest niejawnie wymienialny na uint?

+1

Przypuszczam, że ten sam powód "jednostka x = 0" działa. '0' to podpisana int, chyba że podasz' unit x = 0U'. – vcsjones

+6

Prawdopodobnie 6.1.9 specyfikacji i dyskonto int, ponieważ 0 jest już int. Chociaż ogólnie int nie jest niejawnie wymienialne na uint (6.1.2), można przekształcić * stałe wyrażenie * typu int. –

+0

Jaką wartość ma "0" jako wyrażenie stałe?Czy kompilator po prostu ignoruje rzutowanie jawne '(int)' i traktuje '0' jako stałą' uint'? – Yuck

Odpowiedz

26

Stałe konwersje Integer są traktowane jako bardzo szczególne przez język C#; oto sekcja 6.1.9 specyfikacji:

wyrażenie stałe typu int może być przekształcany do typu sbyte bajt, krótkie USHORT, unit, lub ULong, pod warunkiem, że wartość stałej ekspresji w obrębie zakres docelowego typu. Stała ekspresja typu long może zostać przekształcona na typ ulong, pod warunkiem, że wartość stałego wyrażenia nie jest ujemna.

To pozwala ci robić rzeczy, jak:

byte x = 64; 

które w przeciwnym razie wymagałoby brzydki wyraźnej konwersji:

byte x = (byte)64; // gross 
+12

+1 Bardzo fajnie. Zrobiłbym jednak z '// yuck';) – Yuck

+0

Tak więc w przypadku' uint i = (int) 0; ', kompilator po prostu ignoruje rzutowanie? A może po prostu wynik rzucania stałej ekspresji jest stałą ekspresją? – dlev

+3

@dlev: To ostatnie. Rzucanie stałej wyrażenia typu int na int jest ciągle wyrażeniem stałym. –

9

Poniższy kod wil niepowodzeniem z komunikatem „Nie można niejawnie przekonwertować typu«int»do«uint». Wyraźne konwersji istnieje (czy brakuje obsady?)”

int y = 0; 
uint x = (int)y; 

I to nie powiedzie się „wartość stała«-1»nie mogą być konwertowane do«uint»”

uint x = (int)-1; 

więc jedynym powodem uint x = (int)0; dzieła jest fakt, że kompilator widzi, że 0 (lub jakakolwiek inna wartość> 0) jest stałą czasu kompilacji które można przekształcić w uint

+0

Więc zasadniczo optymalizuje odrzut, ponieważ nie jest potrzebny do literału? – BoltClock

+3

@BoltClock Stałe wyrażenie można konwertować w czasie kompilacji, aby rzutowanie zostało faktycznie usunięte. –

2

Ogólnie kompilatory mają 4 etapy, w których kod jest zamienione. Tekst jest tokenized> Żetony są analizowane> AST jest zbudowany + łączenie> AST jest konwertowane na język docelowy.

Ocena stałych, takich jak liczby i ciągi znaków, występuje jako pierwszy krok, a kompilator prawdopodobnie traktuje 0 jako ważny token i ignoruje rzutowanie.