Kann ich den Rückgabewert ermitteln, bevor ich beim Debuggen in Visual Studio zurückkehre?


387

Übernehmen Sie die folgende Funktion:

DataTable go() {
    return someTableAdapter.getSomeData();
}

Gibt es eine Möglichkeit, den zurückgegebenen Wert zu überprüfen, wenn ich in dieser Funktion einen Haltepunkt setze? go()ist direkt mit einem Datagrid auf einer .aspxSeite verbunden.

Die einzige Möglichkeit, die zurückgegebene Datentabelle zu überprüfen, besteht in der Verwendung einer temporären Variablen. Das ist jedoch etwas unpraktisch. Gibt es nicht einen anderen Weg?


1
Sie können eine Uhr hinzufügen, wenn Sie den Aufrufstapel wieder nach oben bewegen
Chris S

Früher war das in VB6 möglich, ich erinnere mich. Aber damals bestand die Syntax für Funktionen darin, den Wert der Funktion auf den Rückgabewert zu setzen ...
Neil Barnwell

5
Kommentar für Visual C ++ - Benutzer: Geben Sie $ ReturnValue in das Direktfenster oder das Überwachungsfenster ein. Zumindest auf meinem VS 2010 hat es funktioniert!
Sergiol

9
Verwenden Sie für VS2015 $ ReturnValue1 .., falls Sie die 20 Antworten und 100 Kommentare unten nicht durchlesen möchten!
Felickz

3
Was ist die Antwort von 2019 auf all das? Diese Antworten sind super veraltet.
Dylanh724

Antworten:


264

Nicht, dass ich davon Wüste. Beachten Sie, dass , wenn Sie tun eine Variable hinzuzufügen, wird es durch den Compiler in Version baut ohnehin entfernt bekommen ...

Update: Diese Funktionalität wurde zu VS2013 hinzugefügt . Sie können die Rückgabewerte in den Auto-Fenstern sehen oder $ReturnValueim Watch / Instant-Fenster verwenden.

Der Wert kann nur direkt nach der Rückkehr von der Funktion angezeigt werden. Der einfachste Weg, darauf zuzugreifen, besteht darin, einen Haltepunkt auf den Funktionsaufruf zu setzen und den Aufruf zu überspringen (F10).


Update für VS2015: boo! Leider scheint es nicht in VS2015 (devenv v14)
Update für VS2017 zu sein: Es ist zurück. (devenv v15)


12
Der Grund, auf die Temperatur zu verzichten, ist Lesbarkeit und Stil, nicht Effizienz, nicht wahr?
Orip

8
Es ist seit VS 2010 mit IntelliTrace möglich: blogs.msdn.com/b/habibh/archive/2009/10/23/…
Daniel Hilgarth

2
Intellitrace ist nur in VS Ultimate Edition verfügbar.
JMGH

3
@MarcGravell Deine Antwort ist falsch ! Sicher, ich habe sechs Jahre zwischen Ihrer Antwort und der Veröffentlichung dieser Funktion in VS13 durch MS gebraucht, aber immer noch. Wenn Sie nur " vorerst " als Haftungsausschluss hinzugefügt hätten ... (Nein, ich bin nicht zurückgeblieben. Es ist natürlich ein Witz. Sie sind gottähnlich, Kumpel.)
Konrad Viltersten

6
@MarcGravell für VS2015: $ ReturnValue1 funktioniert! (getestet in der ultimativen Version)
GY

58

Dies kann in Visual Studio 2013 mit CLR 4.5.1 gemäß der Kundenfeedback-Site erfolgen . Es war in früheren Versionen für C # nicht verfügbar.

(Visual Studio 2008 und früher haben es für VB.NET unterstützt. Es war immer für C / C ++ - Entwickler verfügbar.)


1
Wie geht das in Visual Studio 2010 C ++?
Benutzer

Laut Microsoft Connect gibt es ein grundlegendes Problem mit verwaltetem Code, das eine zuverlässige Implementierung verhindert:
Dan Solovay,

@DanSolovay Die Wörter, die sie verwenden, sind "wir konnten nicht konsequent das Richtige tun" (für VS11), aber sie "wollen dies zurückbringen" und "suchen nach einer Reihe möglicher Lösungen für dieses Problem".
Alex Angas

Der Verbindungseintrag ist veraltet. Die Funktion scheint ... aufgegeben zu sein: ((
Softlion

1
Es ist seit VS 2010 mit IntelliTrace möglich: blogs.msdn.com/b/habibh/archive/2009/10/23/…
Daniel Hilgarth

25

Ich bin damit einverstanden, dass dies eine sehr nützliche Sache ist: Sie müssen nicht nur den Rückgabewert der Methode sehen, bevor Sie sie verlassen, sondern auch den Rückgabewert der Methoden, die ich gerade überschritten habe. Ich habe es als Teil einer kommerziellen Erweiterung von Visual Studio namens " OzCode " implementiert .

Damit können Sie Methodenrückgabewerte direkt im Code-Editor als eine Art HUD-Anzeige anzeigen:

Anweisungsvisualisierung

Weitere Informationen finden Sie in diesem Video .


23

Laut Microsoft gibt es keine Möglichkeit, dies mit verwaltetem Code zuverlässig zu implementieren. Dies ist ein Problem, das sie kennen und an dem sie arbeiten:

Für diejenigen da draußen, die Erfahrung mit dem Debuggen von nativem C ++ - oder VB6-Code haben, haben Sie möglicherweise eine Funktion verwendet, bei der Funktionsrückgabewerte im Fenster "Autos" für Sie bereitgestellt werden. Leider ist diese Funktionalität für verwalteten Code nicht vorhanden. Sie können dieses Problem umgehen, indem Sie die Rückgabewerte einer lokalen Variablen zuweisen. Dies ist jedoch nicht so praktisch, da Sie Ihren Code ändern müssen. In verwaltetem Code ist es viel schwieriger, den Rückgabewert einer Funktion zu bestimmen, über die Sie gegangen sind. Wir haben festgestellt, dass wir hier nicht konsequent das Richtige tun können, und haben die Funktion entfernt, anstatt Ihnen im Debugger falsche Ergebnisse zu liefern. Wir möchten dies jedoch für Sie zurückbringen, und unsere CLR- und Debugger-Teams suchen nach einer Reihe möglicher Lösungen für dieses Problem. Leider wird dies nicht Teil von Visual Studio 11 sein.

https://connect.microsoft.com/VisualStudio/feedback/details/597933/add-a-return-pseudo-variable-to-the-visual-studio-debugger-for-net-code


1
Gemäß @Alex oben ( stackoverflow.com/a/3714884/402949 ) ist dies für VS2013 mit CLR 4.5 verfügbar
Dan Solovay

21

In Bezug auf Visual Studio 2015:

Nach der derzeit akzeptierten Antwort von Marc Gravell:

Diese Funktionalität wurde zu Visual Studio 2013 hinzugefügt . Sie können die Rückgabewerte in den Auto-Fenstern sehen oder $ ReturnValue im Watch / Instant-Fenster verwenden

In dieser Antwort wurde auch angegeben, dass diese Funktionalität in Visual Studio 2015 nicht funktioniert. Dies ist nicht (vollständig) wahr. Bei der Überprüfung der Rückgabewerte von Methodenaufrufen wird der folgende Hinweis angezeigt:

Sie müssen die Legacy-Ausdrucksauswerter aktiviert haben , damit $ ReturnValue erkannt wird (Tools / Optionen / Debugging / Verwenden Sie die Legacy-C # - und VB-Ausdrucksauswerter ). Andernfalls können Sie $ ReturnValue1 verwenden .

Ich habe dies in Visual Studio 2015 Enterprise getestet:

  • Bei deaktivierten Legacy-Ausdrucksauswertern funktioniert nur $ ReturnValue1
  • Mit Vermächtnis Ausdruck Gutachter eingeschaltet: sowohl $ Return und $ ReturnValue1 Arbeit

3
Dies scheint nicht mehr notwendig zu sein. In VS 2015 Update 3 sind ältere Evaluatoren deaktiviert und $ReturnValuefunktionieren. Der Rückgabewert wird jedoch nirgendwo angezeigt, wenn Sie die Use managed compatibility modeDebugging-Option aktiviert haben.
Nick

13

Wenn Sie zum Menü ExtrasOptionen , IntelliTrace gehen und die Einstellung ändern, um Ereignisse und Anrufinformationen zu erfassen.

Sie können zum vorherigen Aufrufereignis ( Ctrl+ Shift+ F11) zurückkehren und den vom Methodenaufruf zurückgegebenen temporären Wert im Auto-Fenster als untergeordnetes Element des Methodennamens anzeigen.

Hier wird nicht der Rückgabewert für die Methode angezeigt, in der Sie sich befinden. Es wird nur der Rückgabewert der zuletzt in der aktuellen Methode aufgerufenen Methode angezeigt.

Also ist es gut für

DataTable go(){return someTableAdapter.getSomeData();}

wie es Ihnen den Rückgabewert für zeigt someTableAdapter.getSomeData().

Aber nicht für:

int go(){return 100 * 99;}

12

Alter Trick aus der Zeit vor .NET: Öffnen Sie das Registerfenster und sehen Sie sich den Wert des EAX-Registers an. Dies enthält den Rückgabewert der zuletzt aufgerufenen Funktion.


1
+1 für Old School näher am Metal-Ansatz - dies funktioniert jedoch nicht für alle Rückgabewerte (und es liegt natürlich am JIT'er - wer weiß, für welche verrückte Optimierung es sich entscheiden könnte, dass EAX nicht verwendet wird? ). Für integrale Typen wird es (meistens?) Funktionieren. Große Werttypen sind eine andere Sache (und soweit ich mich an einen Blog-Beitrag erinnere, werden diese auch in VS2013 nicht angezeigt).
JimmiTh

10

Verlassen Sie die go () -Methode mit Shift-F11 und zeigen Sie dann im Debug-Fenster "Autos" den Rückgabewert des Methodenaufrufs an, der gerade vom Stapel gesprungen ist (in diesem Fall die go () -Methode) was du willst). Dies ist das Verhalten in Visual Studio 2005. Ich habe Visual Studio 2008 nicht verwendet, daher weiß ich nicht, ob sich dies in dieser Version genauso verhält.


Ich habe dies sowohl in VS2005 als auch in VS2008 versucht, aber ich sehe es nicht wirklich. Ich habe das "Autos" -Fenster geöffnet, aber wenn in der "go" -Funktion, ist das Autos-Fenster nur leer. Auch beim Verlassen der Funktion (die schließende geschweifte Klammer der Funktion ist gelb). Können Sie mir noch einen Hinweis geben?
Doekman

Ich würde erwarten, dass das Autos-Fenster leer ist, während INSIDE die Funktion go (). Sie müssen die Funktion VOLLSTÄNDIG verlassen (dh der Debug-Cursor sollte auf die Funktion zeigen, die go () aufgerufen hat), und dann sollte der Rückgabewert für go () im Fenster Autos angezeigt werden.
LeopardSkinPillBoxHat

@LeopardSkinPillBoxHat: Ich kann das nicht zum Laufen bringen, selbst mit Ihrem zusätzlichen Hinweis. Versuchen Sie dies in Visual Basic? Es scheint eine bessere Unterstützung für das Beobachten und Ändern von Rückgabewerten zu haben ...
Roman Starkov

@romkyns - Was wird für Sie im Fenster "Autos" angezeigt? Zeigt es keine Zeile an, die angibt, was die zuletzt aufgerufene Funktion zurückgegeben hat?
LeopardSkinPillBoxHat

2
@LeopardSkinPillBoxHat: Nein, das macht es in C # nicht. PS Wow, ich habe eine Weile gebraucht, um das wieder zu sehen.
Roman Starkov

7

Ja, es gibt einen sehr schönen Weg. Ein wesentlicher Nachteil ist, dass Sie 5, vielleicht 6 Jahre warten müssen. Da ich sehe, dass Sie im November 2008 gepostet haben, schlage ich vor, dass Sie waaaaaa ...

... aaaait. Und voilà! Nur für Sie hat MS das neueste Visual Studio 2013 veröffentlicht, bei dem es sich um eine Standardfunktion handelt, auf die über die Menüs zugegriffen werden kann, während sie im Debug-Modus ausgeführt werden (Menü DebugWindowsAutos ).


@Doug Weil die Frage im November 2008 gestellt wurde und meine Antwort im September 2014 kam. Das Originalplakat ist wahrscheinlich zufrieden und möchte den Kredit nicht verschieben. Aber ich stimme Ihnen zu - es würde mir nichts ausmachen, wenn meine Antwort noch ein paar Upsies enthält. Ich mag Upsies und Rep Gain. :)
Konrad Viltersten

Hatte dieses Problem heute. Vielen Dank für Ihre Antwort im Jahr 2014, obwohl die erste Ausgabe 2008 ist. Ihre Antwort ist genau das, wonach ich gesucht habe.
AP

@AP Keine Probleme. Fühlt sich ein bisschen wie eine Zeitmaschine an, um diesen Beitrag zu sehen. Explosion aus der Vergangenheit, hehe.
Konrad Viltersten

5

Es gibt viele Problemumgehungen, aber keine scheint zufriedenstellend zu sein.

Um John Skeet unten zu zitieren (Kommentar zu einer jetzt gelöschten Antwort):

Sieht für mich immer noch unpraktisch aus - insbesondere, wenn Sie nicht wissen, welchen Rückgabewert Sie benötigen, bevor Sie mit dem Debuggen beginnen. Ich möchte wirklich nicht, dass jedes Mal, wenn ich etwas zurückgebe, eine temporäre Variable meinen Code überfüllt

Theoretisch könnte der Debugger eine return-variable haben. Immerhin: Es ist nur eine Variable auf dem Stapel:

unsafe {
  int * sp = stackalloc int[1];
  try {
    return a+b;
  }
  finally {
    Trace.WriteLine("return is " + *(sp+3));
  }
}

Betrachten Sie dies als eine Funktionsanforderung für Visual Studio.


Es gibt einen ziemlich großen Unterschied zwischen einer Variablen (einem genau definierten lokalen Wert) und einem Wert auf dem Stapel. Es ist ein Wert auf dem Stapel, aber keine Variable (= lokal).
Marc Gravell

@Marc: Ich bin nicht sicher, wie die CLR funktioniert, aber viele Compiler setzen Funktionsargumente auf den Stapel unter dem Stapelzeiger (sp) und lokale Variablen auf den Stapel über dem Stapelzeiger. Genau das versuche ich zu zeigen. Und OK, wenn der Rückgabewert ein Referenztyp ist, erhalten Sie nur einen Zeigerwert.
Doekman

1
Es ist nicht unbedingt auf dem Stapel. In der Tat, wenn Sie Debug -> Register
anzeigen

5

Ich wollte die Antwort von PascalK erweitern , damit dies in Visual Studio 2015 funktioniert, da es eine versteckte Funktion gibt, die in Untersuchen der Rückgabewerte von Methodenaufrufen nicht dokumentiert ist .

Wenn Sie verschachtelte Funktionsaufrufe haben, werden die Pseudovariablen $ResultValueXautomatisch erstellt, wobei sich das X auf die Funktionsaufrufreihenfolge bezieht. Wenn Sie also einen Aufruf wie haben Multiply(Five(), Six()), werden die folgenden Pseudovariablen erstellt:

Five()     | $ResultValue1 = 5
Six()      | $ResultValue2 = 6
Multiply() | $ResultValue3 = 30

2

Microsoft Visual C ++ hat dies früher getan, Visual Studio jedoch nicht AFAIK .. :(


2

Die einzige Möglichkeit, die ich kenne, besteht darin, einen Haltepunkt in die Rückgabezeile zu setzen, dann das Quick Watch- Fenster aufzurufen und den zurückgegebenen Ausdruck einzugeben:

someTableAdapter.getSomeData();

Dies funktioniert jedoch nur, wenn der Aufruf den Status eines Objekts nicht ändert (da dieselbe Methode erneut aufgerufen wird, wenn Sie die Ausführung fortsetzen).


5
Dies funktioniert auch nur, wenn Ihr Ausdruck keine Lambdas enthält.
Roman

1

Sie können auch fragen, ob der Wert im Zwischenfenster ausgewertet werden soll, wenn keine Flags oder andere Variablen gesetzt werden, sondern nur etwas zurückgegeben wird.


Sie müssen das Lambda in die Frage aufnehmen, da ich manchmal auch das unmittelbare Fenster benutze
Chris S

1

Ich denke, Sie können dies feststellen, indem Sie das RAX-Register im Registerfenster (Debug / Windows / Register) betrachten. Überprüfen Sie nach dem Verlassen der Funktion (UMSCHALT + F11) das RAX-Register. Ich weiß es nicht genau, aber wenn es einmal Mond war, konnten Sie ein Register überprüfen (vor .NET Tagen) und dort den Rückgabewert sehen. Es könnte sogar eine Kombination aus RAX und RBX usw. sein.


1

Wenn Sie das Fenster Debug → Autos öffnen, werden Sie geschlossen. Es wird nicht der tatsächliche Rückgabewert angezeigt, aber es wird angezeigt, was in der return-Anweisung ausgewertet wurde.


2
Das VS2008-Autofenster konnte so etwas nicht anzeigen. Kannst du das bitte klären?
Roman Starkov

return x + y; Ich meinte, wenn Sie in dieser Zeile einen Haltepunkt setzen, zeigt Ihr Debug-Autos-Fenster die aktuellen Werte für x und y an. Wie gesagt, es bringt dich nur in die Nähe. Ich versuche nur hilfreich zu sein. Ich denke nicht, dass das eine Ablehnung verdient.
GeekyMonkey

1

Ja, indem Sie zu VB.NET wechseln. ; P (Du hast gerade "Visual Studio" gesagt .;)

Solange ich mich erinnern kann (von Visual Basic bis zu allen Versionen von VB.NET), können Sie einfach den Funktionsnamen abfragen. Es "funktioniert" wie eine lokale Variable, die zu Beginn der Funktion implizit deklariert wird, und ihr aktueller Wert wird auch als Rückgabewert verwendet, wenn die Funktion über ein Non-Return-Anweisungsmittel beendet wird (dhExit Function oder nur durchfällt) und natürlich, wenn Die return-Anweisung wird verwendet.

Es wird auch auf den Ausdruck der return-Anweisung gesetzt. Genau wie bei einer lokalen Variablen kann ihr Wert an jedem Ausführungspunkt innerhalb der Funktion überprüft werden (auch nachdem die return-Anweisung ausgeführt wurde). C # hat das nicht und sollte.

Diese kleine VB.NET-Funktion (plus die Exit FunctionAnweisung, die sie aktiviert - eine andere Funktion, die C # nicht hat und sollte) ist sehr nützlich in einer Form der defensiven Programmierung, die ich praktiziere und bei der ich den Funktionsnamen immer mit dem Fehler- / Standardwert als initialisiere erste Aussage. Dann kann ich an jedem Fehlerpunkt (der normalerweise viel häufiger auftritt als Erfolgspunkte) einfach die Exit FunctionAnweisung aufrufen (dh ohne den Fehler- / Standardausdruck oder sogar einen Konstanten- / Variablennamen duplizieren zu müssen).


1

Die akzeptierte Antwort funktioniert mit Visual Studio 2015 nicht ordnungsgemäß. Wenn Sie jedoch einen Haltepunkt in die letzte Zeile der Methode setzen und drücken F10, werden alle Ausdrücke des Rückgabewerts in das lokale Fenster eingefügt.


Sie können die akzeptierte Antwort wahrscheinlich auch bearbeiten, um Ihre Kommentare einzuschließen.
Doekman

0

Sie können versuchen, auszuwählen "someTableAdapter.getSomeData();", mit der rechten Maustaste darauf zu klicken und sich für die Schnellüberwachung zu entscheiden .


-1

Ziehen Sie den Rückgabeausdruck per Drag & Drop in ein Überwachungsfenster.

Zum Beispiel in der Anweisung

return someTableAdapter.getSomeData();

Drag & Drop

someTableAdapter.getSomeData()

in ein Überwachungsfenster, und Sie sehen den Wert.

Sie können dies für jeden Ausdruck tun.


2
Das Problem dabei: Der Ausdruck wird zweimal ausgewertet.
Doekman

6
Und Watch-Ausdrücke können keine Lambda-Ausdrücke enthalten, die ich ziemlich oft benutze.
Steve Crane
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.