Vor einiger Zeit habe ich zwei Versionen eines Codes kompiliert, einen mit (Nullable<T>)x.GetValueOrDefault(y)
und einen mit (Nullable<T>)x ?? y)
.
Nach dem Dekompilieren nach IL habe ich festgestellt, dass der Nullkoaleszenzoperator in den GetValueOrDefault
-Aufruf umgewandelt wird.
Da es sich um einen Methodenaufruf handelt, an den ein Ausdruck übergeben werden kann, der vor der Ausführung der Methode ausgewertet wird, wird y
immer ausgeführt.
Zum Beispiel:
%Vor%Scheint zu einem unpopierten Objekt und wahrscheinlich auch zu Auswirkungen auf die Leistung zu führen.
Erstens, ist das wahr? Oder ändert der JIT oder etwas Ähnliches den tatsächlich ausgeführten ASM-Code?
Und zweitens kann jemand erklären, warum es dieses Verhalten hat?
HINWEIS: Dies ist nur ein Beispiel, es basiert nicht auf echtem Code, und bitte machen Sie keine Kommentare wie 'das ist schlechter Code'.
IL DASM:
Okay, als ich dies mit .Net Framework 2.0 kompiliert habe, ergab sich identischer Code mit dem Aufruf von null coalesce und GetValueOrDefault. Mit .Net Framework 4.0 generiert es diese zwei Codes:
GetValueOrDefault:
%Vor%Nullkoaleszenz:
%Vor% Es stellt sich heraus, dass dies nicht länger der Fall ist und dass es den GetValueOrDefault
-Aufruf komplett überspringt, wenn HasValue
false zurückgibt.
Nach dem Dekompilieren nach IL habe ich festgestellt, dass der Nullkoaleszenzoperator in den GetValueOrDefault-Aufruf umgewandelt wird.
x ?? y
wird in x.HasValue ? x.GetValueOrDefault() : y
umgewandelt. Es wird nicht in x.GetValueOrDefault(y)
umgewandelt, und es wäre ein Compiler Bug, wenn es so wäre. Sie haben Recht, y
sollte nicht ausgewertet werden, wenn x
nicht null ist, und das ist es nicht.
Bearbeiten : Wenn die Auswertung von y
frei von Nebenwirkungen sein kann (wobei "Nebeneffekt" "eine Ausnahme auslöst"), würde eine Umwandlung in x.GetValueOrDefault(y)
nicht erfolgen Es ist natürlich falsch, aber es ist immer noch eine Transformation, die der Compiler nicht ausführt: Es gibt nicht viele Situationen, in denen diese Optimierung nützlich wäre.