Das ist wirklich komisch. Ich habe diesen Fehler ausfindig gemacht:
Die Negierung des Minimalwerts einer Zweierkomplementnummer ist ungültig.
... und es stellte sich heraus, dass es Code wie folgt war:
%Vor%Wenn ich das in LINQPad ausführe:
%Vor%... es gibt mir:
-2147483648
Allerdings sagt ein anderer Entwickler hier, dass er etwas völlig anderes bekommt (nicht in LINQPad):
-1141206336
Wenn ich versuche, nur den Cast für sich selbst auf einer Konstante zu bewerten:
%Vor% ... Ich bekomme einen Kompilierfehler, weil unchecked
benötigt wird. Und das:
... ergibt -1141206336
wie der andere Entwickler. Ich dachte also, dass Convert
einen subtil anderen Wert als die Konstante erzeugt. Nein, dies ergibt True
:
Was zum Teufel geht hier vor? Warum führt die Auswertung dieser scheinbar identischen Ausdrücke zu so unterschiedlichen Ergebnissen?
Aktualisieren :
Ich habe einen Hinweis gefunden. Die hexadezimale Repräsentation von 4.70259123E14
und -1141206336
ist:
Ich denke also, einer der Casts schiebt die Bits direkt in das int
. Also -2147483648
ist das größere Geheimnis.
Ich bin mir nicht ganz sicher, was der Grund ist, aber es sieht wie ein Compilerfehler aus, weil ein Programm, das mit Roslyn kompiliert wurde, den gleichen Wert (-2147483648) für beide Ausdrücke liefert.
Der Compiler darf konstante Ausdrücke zur Kompilierzeit auswerten. Alle Konvertierungen mit dem ungeprüften Ausdruck werden vom Compiler ausgeführt, im anderen Fall werden sie zur Laufzeit von der CLR ausgeführt, so dass immer die Möglichkeit besteht, dass sie leicht unterschiedliche Regeln verwenden. Wie Sie gesehen haben, scheint der Compiler anders als die Laufzeit abgeschnitten zu haben, um den Wert in eine 32-Bit-Ganzzahl zu bringen. Sie können in der zugrunde liegenden IL sehen, dass das Programm nur den konstanten Wert (0xbbfa92c0) anstelle des ungeprüften Ausdrucks lädt.
%Vor%Decompiled IL von .NET 4.5 Compiler:
%Vor%