Zastanawiam się dlaczego w C# poniższych jest w porządku:Dlaczego jest x ++ - + - ++ x legal, ale x +++ - +++ x nie jest?
int y = x++-+-++x;
Ale
int y = x+++-+++x;
nie? Dlaczego istnieje odchylenie od +?
Zastanawiam się dlaczego w C# poniższych jest w porządku:Dlaczego jest x ++ - + - ++ x legal, ale x +++ - +++ x nie jest?
int y = x++-+-++x;
Ale
int y = x+++-+++x;
nie? Dlaczego istnieje odchylenie od +?
Pozostałe dwie odpowiedzi są poprawne; Dodam do nich, że to ilustruje pewne podstawowe zasady analizy leksykalnej:
Zasady te oznaczają, że +++x
będą lexed jak ++ + x
a nie + ++ x
.
Parser następnie analizować ++ + x
jako ++(+x)
i (+x)
nie jest zmienny, to jest wartość, a więc nie może być zwiększony.
Zobacz także: http://blogs.msdn.com/b/ericlippert/archive/2010/10/11/10070831.aspx
+1, chociaż mogłoby to uczynić go nieparzystym że Mono może skompilować ten sam kod. Albo specyfikacja jest nieco "otwarta" po tej stronie, albo jeden z kompilatorów nie jest do końca zgodny. –
@JoachimIsaksson: Mono ma mały błąd; Podejrzewam, że znajduje się on w analizatorze semantycznym, a nie w analizatorze leksykalnym. Oznacza to, że nie jest ** przypadkiem, że Mono porównuje '+++ x' jako' + ++ x'. Raczej podejrzewam, że jest to poprawnie poprawne jako '++ + x', następnie analizator semantyczny traktuje' + x' jako 'x', ale zapominając, że' + x' jest wartością, a nie zmienną, a zatem nie kwalifikuje się jako operand inkrementacji. –
@JoachimIsaksson: Rzeczywiście. Kompilator Microsoft C# zawierał wiele tego rodzaju błędów w C# 2.0; Usunąłem ich dużo w C# 3.0. Kilku, których zatrzymaliśmy, ponieważ byli nieszkodliwi i podjęcie przełomowej zmiany byłoby destrukcyjne. –
Używam VS 2012. Jest to interesujące.
Pierwszy z nich może być analizowany w:
int y = (x++) - (+(-(++x)));
nie zmieniając wynik końcowy. Więc możesz zobaczyć, dlaczego byłaby ważna.
Drugi ma jednak problem z +++x
, ponieważ (domyślam się) widzi dwie ++ i próbuje zastosować ten jednoargumentowy operator do wartości r, która jest kolejnym + (a nie poprawna wartość r). Można grupa go na różne sposoby, aby to działało, choć:
int y = (x++)+(-(+(++x)));
jest prawidłowy.
Jestem pewien, że Jon Skeet lub Eric Lippert lub ktoś pojawi się i wskaże odpowiednią część specyfikacji C#. Nie jestem nawet pewien, od czego zacząć. Ale po ogólnym analizowaniu tokenu od lewej do prawej widać, gdzie dusi się na drugim.
FYI cała gramatyka znajduje się na końcu specyfikacji w dodatku. –
Nie widać nic poza "jednym z" gramatyki operatora, czy preferować '+' lub '++' na dowolnym etapie wydaje się niejasne. –
@JoachimIsaksson: Sekcja 2.3 specyfikacji mówi: "Gdy kilka leksykalnych przedstawień gramatycznych pasuje do sekwencji znaków w pliku źródłowym, przetwarzanie leksykalne zawsze stanowi najdłuższy możliwy element leksykalny." * –
Kompilator szuka zmiennej lub właściwości po drugim ++
w int y = x+++-+++x
i nie może tego ustalić bez spacji lub nawiasów.
można zrobić coś takiego:
int y = x+++-+(++x);
lub
int y = x++ + -+ ++x;
jeśli chciałeś.
Powód, dla którego pierwszy wymieniony przykład zadziałał, jest taki, że kompilator może określić, że +-
z ++x
; podczas gdy w drugim przykładzie nie może on ustalić, gdzie oddzielić +++
i naturalnie oczekuje zmiennej po przeczytaniu pierwszego ++
; tak w skrócie, kompilator próbuje użyć +x
jako zmiennej, która jest nieprawidłowa.
Obie są prawdopodobnie poprawne przy użyciu innego kompilatora. To zależy od semantyki.
Lepsze pytanie brzmi: dlaczego chcesz tego użyć? – Sayse
To zależy od kompilatora (.Net 4.5 na VS 2012 narzeka) –
Potrzebujemy szczegółów na temat używanego kompilatora, na jakie .NET kierujesz swoje reklamy, itp. – tnw