Wenn (false == true) einen Block ausführt, wenn eine Ausnahme ausgelöst wird

152

Ich habe ein ziemlich seltsames Problem, das auftritt.

Das ist mein Code:

private async Task BreakExpectedLogic()
{
    bool test = false;
    if (test == true)
    {
        Console.WriteLine("Hello!");
        throw new Exception("BAD HASH!");
    }
}

Scheint wirklich einfach, es sollte nicht das Console.WriteLineoder das treffen throw. Aus irgendeinem Grund trifft es immer die throw.

Wenn ich das throwin eine eigene Methode verschiebe, funktioniert es einwandfrei. Meine Frage ist, wie es ist, den ifBlock zu ignorieren und das zu treffen throw new Exception:

Hier sind einige Beweise

BEARBEITEN 1: Ich habe meinen Code so aktualisiert, dass er die Signatur enthält. Ich habe alles entfernt, was nicht mit diesem Problem zusammenhängt, und es ausgeführt. Es passiert immer noch.

George
quelle
5
@ TimSchmelter das Bild wird debuggt, das gelbe Highlight ist, wo der Code ist
George
5
Ich habe gerade eine leere Core-Konsolen-App erstellt und nur Ihren Code in die Mainund ... Überraschung, norepro eingefügt. Entweder Sie irren sich oder Sie haben ein wichtiges Detail übersehen.
Jamiec
16
Ist das asynczufällig eine Methode? Weil es ähnlich zu stackoverflow.com/questions/42528458/…
Matthew Watson
7
@ George: Immer noch keine Beweise, weil Sie möglicherweise alte Debug-Symbole verwenden. Im Debug-Modus neu kompilieren und dann erneut starten.
Tim Schmelter
4
@ TimSchmelter Ich habe das Projekt neu kompiliert, bereinigt und wieder
George

Antworten:

176

Es scheint der Fehler in der asyncMethode zu sein, der Code wird nicht tatsächlich ausgeführt, sondern der Debugger geht mit der throwAnweisung in die Zeile . Wenn einige Codezeilen vorhanden sind, bevor die throwAnweisung in ifdiesen Zeilen ignoriert wird, wechselt der Debugger nur zu der Zeile mit der throwAnweisung.

Wenn Sie keine Variablen verwenden - if (false)oder if (true == false)dann Debugger-Schritte zur richtigen Codezeile -, wird die schließende geschweifte Klammer verwendet.

Dieser Fehler wurde von @Matthew Watson im Visual Studio-Team veröffentlicht (Link ist derzeit nicht verfügbar).

Siehe auch ähnliche Frage - Bedingungsprüfung in asynchroner Methode

BEARBEITEN (06.10.2017):

Das Problem kann in VS 2017 15.3.5 mit .Net Framework 4.7 nicht reproduziert werden. Das VS-Team hat dieses Problem anscheinend behoben.

Roman Doskoch
quelle
20
Vielen Dank, ohne zu wissen, dass dies ein Fehler im Debugger ist, wäre ich wahrscheinlich verrückt geworden.
George
121
Ein Fehler im Debugger? Wie sehr meta. :) (Gesang habe ich noch nie so einen Meta-Bug gemacht ... )
Simba
3
@George Ich hoffe, es macht Ihnen nichts aus. Ich habe Ihr Beispiel genommen und eine Konsolen-App damit erstellt und es an das VS-Problem angehängt, mit dem Roma verlinkt hat.
Obsidian Phoenix
5
@ Simba: Sag mir, dass du noch nie einen Debugger benutzt hast, um dich selbst zu debuggen.
Joshua
3
Hmm. Es scheint, dass der Fehler eher in den vom Compiler generierten Debug-Informationen als im Debugger selbst liegen könnte. Ich werde warten, bis MS den Connect-Fehler bestätigt, bevor ich nach oben oder unten stimme.
Adrian McCarthy
10

Nur ein Nachtrag zur Antwort. Ich bin kürzlich auf dasselbe Problem gestoßen und habe mir den tatsächlichen x86-Code im Debugger angesehen. Er wurde auf seltsame Weise wie folgt generiert (vereinfacht):

// if (...) {
0001: jne 0006
...
0006: jmp 0007
// }
0007: ret

Anstatt direkt zu den letzten Anweisungen der Methode zu springen, wird ein Doppelsprung ausgeführt, bei dem der zweite bedingungslose Sprung meines Erachtens fälschlicherweise als Teil des Codes innerhalb des ifBlocks erkannt wird .

Ich würde also spekulieren, dass dieser Fehler mit dem JIT-Compiler zusammenhängt.

Serge Semenov
quelle