Posso scoprire il valore restituito prima di tornare durante il debug in Visual Studio?


387

Prendi la seguente funzione:

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

Quando imposto un punto di interruzione in questa funzione, c'è la possibilità di ispezionare il valore restituito? go()è direttamente accoppiato a un datagrid in una .aspxpagina.

L'unico modo per ispezionare il datatable restituito è utilizzare una variabile temporanea. Tuttavia, è un po 'scomodo. Non c'è un altro modo?


1
È possibile aggiungere un orologio se si sale di nuovo nello stack di chiamate
Chris S

Un tempo potevi farlo in VB6, mi sembra di ricordare. Ma allora la sintassi delle funzioni comportava l'impostazione del valore della funzione sul valore di ritorno ...
Neil Barnwell,

5
Commento per gli utenti di Visual C ++: digitare $ ReturnValue nella finestra immediata o nella finestra di controllo. Almeno sul mio VS 2010 ha funzionato!
sergiol,

9
Per VS2015 usa $ ReturnValue1 .. nel caso in cui non desideri leggere le 20 risposte e i 100 commenti qui sotto!
Felickz,

3
Qual è la risposta del 2019 a tutto questo? Queste risposte sono super datate.
dylanh724,

Risposte:


264

Non che io sappia. Si noti che se si fa aggiungere una variabile, otterrà rimosso dal compilatore nel rilascio costruisce comunque ...

Aggiornamento: questa funzionalità è stata aggiunta a VS2013 . È possibile visualizzare i valori restituiti nelle finestre delle auto o utilizzare $ReturnValuenella finestra dell'orologio / immediata.

Il valore può essere visualizzato direttamente dopo il ritorno dalla funzione, quindi il modo più semplice per accedervi è inserire un punto di interruzione nella chiamata di funzione e passare (F10) alla chiamata.


Aggiornamento per VS2015: boo! sfortunatamente, non sembra essere nell'aggiornamento VS2015 (devenv v14)
per VS2017: è tornato. (devenv v15)


12
Il motivo per rinunciare alla temperatura è la leggibilità e lo stile, non l'efficienza, no?
Orip,

8
È possibile dal VS 2010 con IntelliTrace: blogs.msdn.com/b/habibh/archive/2009/10/23/…
Daniel Hilgarth,

2
Intellitrace è disponibile solo in VS Ultimate Edition.
JMGH,

3
@MarcGravell La tua risposta è sbagliata ! Certo, mi ci sono voluti sei anni tra la tua risposta e la pubblicazione di MS su quella funzione in VS13, ma comunque. Se avessi avuto solo aggiunto " per il momento ", come un disclaimer ... (No, io non sono ritardato Si. È uno scherzo, Certo che sei simile a Dio, amico..)
Konrad Viltersten

6
@MarcGravell per VS2015: $ ReturnValue1 funziona! (testato nella versione definitiva)
GY

58

Questo può essere fatto in Visual Studio 2013 con CLR 4.5.1 in base al sito di feedback dei clienti . Non era disponibile nelle versioni precedenti per C #.

(Visual Studio 2008 e versioni precedenti lo supportavano per VB.NET. È sempre stato disponibile per gli sviluppatori C / C ++.)


1
Come si fa in Visual Studio 2010 C ++?
Utente

Microsoft Connect afferma che esiste un problema fondamentale con il codice gestito che impedisce l'implementazione in modo affidabile:
Dan Solovay,

@DanSolovay Le parole che usano sono "non potevamo fare la cosa giusta in modo coerente" (per VS11) ma "vogliono riportare questo" e "stanno cercando un numero di potenziali soluzioni a questo problema".
Alex Angas,

La voce di connessione è obsoleta. La funzione sembra essere ... abbandonata: ((((
Softlion

1
È possibile dal VS 2010 con IntelliTrace: blogs.msdn.com/b/habibh/archive/2009/10/23/…
Daniel Hilgarth,

25

Concordo sul fatto che questa sia una cosa molto utile: non solo vedere il valore di ritorno del metodo prima di uscirne, ma anche vedere il valore di ritorno dei metodi che ho appena superato. L'ho implementato come parte di un'estensione commerciale di Visual Studio chiamata " OzCode ".

Con esso, puoi visualizzare i valori di ritorno del metodo direttamente sull'editor di codice, come una sorta di display HUD:

Visualizzazione delle dichiarazioni

Per ulteriori informazioni, consulta questo video .


23

Secondo Microsoft, non c'è modo di implementarlo in modo affidabile con il codice gestito. Questo è un problema di cui sono a conoscenza e su cui stanno lavorando:

Per coloro che hanno esperienza nel debug del codice C ++ o VB6 nativo, è possibile che sia stata utilizzata una funzionalità in cui i valori di ritorno della funzione sono forniti nella finestra Autos. Sfortunatamente, questa funzionalità non esiste per il codice gestito. Sebbene sia possibile aggirare questo problema assegnando i valori restituiti a una variabile locale, ciò non è altrettanto conveniente perché richiede la modifica del codice. Nel codice gestito, è molto più complicato determinare quale sia il valore restituito di una funzione su cui si è passati. Ci siamo resi conto che non potevamo fare la cosa giusta in modo coerente qui e quindi abbiamo rimosso la funzione piuttosto che darti risultati errati nel debugger. Tuttavia, vogliamo ripristinarlo e i nostri team CLR e Debugger stanno esaminando una serie di potenziali soluzioni a questo problema. Purtroppo questo non farà parte di Visual Studio 11.

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


1
Per @alex sopra ( stackoverflow.com/a/3714884/402949 ), questo è disponibile per VS2013 con CLR 4.5
Dan Solovay

21

Per quanto riguarda Visual Studio 2015:

Secondo la risposta attualmente accettata da Marc Gravell:

Questa funzionalità è stata aggiunta a Visual Studio 2013 . Puoi vedere i valori di ritorno nelle finestre delle auto o usare $ ReturnValue nella finestra watch / immediate

Questa risposta ha anche affermato che questa funzionalità non funziona in Visual Studio 2015. Questo non è (interamente) vero. Su Esamina i valori di ritorno delle chiamate di metodo è presente la seguente nota:

È necessario che i valutatori di espressioni legacy siano attivati ​​affinché $ ReturnValue sia riconosciuto (Strumenti / Opzioni / Debug / Usa i valutatori di espressioni C # e VB legacy ). Altrimenti, puoi usare $ ReturnValue1 .

Ho provato questo in Visual Studio 2015 Enterprise:

  • Con i valutatori di espressioni legacy disattivati: solo $ ReturnValue1 opere
  • Con legacy analizzatori di espressioni accesi: sia $ ReturnValue e $ ReturnValue1 lavoro

3
Questo non sembra più essere necessario. Su VS 2015 Update 3, ho disabilitato i valutatori legacy e $ReturnValuefunziona. Tuttavia, il valore restituito non viene visualizzato da nessuna parte se l' Use managed compatibility modeopzione di debug è abilitata.
Nick,

13

Se vai al menu StrumentiOpzioni , IntelliTrace e modifichi l'impostazione per raccogliere eventi e informazioni sulla chiamata.

Puoi tornare all'evento di chiamata precedente ( Ctrl+ Shift+F11 ) e vedere il valore temporaneo restituito dalla chiamata del metodo nella finestra delle auto come figlio del nome del metodo.

Questo non ti mostra il valore di ritorno per il metodo in cui ti trovi. Ti mostra solo il valore di ritorno dell'ultimo metodo chiamato nel metodo corrente.

Quindi, va bene per

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

poiché mostra il valore restituito per someTableAdapter.getSomeData().

Ma non per:

int go(){return 100 * 99;}

12

Vecchio trucco dei giorni precedenti a .NET: apri la finestra Registri e osserva il valore del registro EAX. Questo contiene il valore restituito dell'ultima funzione chiamata.


1
+1 per la vecchia scuola più vicino all'approccio metal - questo, tuttavia, non funzionerà per tutti i valori di ritorno (e spetta ovviamente al JIT'er - chissà su quale pazza ottimizzazione potrebbe decidere che non utilizzerà EAX? ). Per i tipi integrali funzionerà (principalmente?). I tipi di valore di grandi dimensioni sono una questione diversa (e per quanto ricordo da alcuni post del blog, questi non verranno visualizzati neanche in VS2013).
Jimmi,

10

Esci dal metodo go () usando Shift-F11, quindi nella finestra di debug "Autos" mostrerà il valore di ritorno della chiamata del metodo che è appena saltato fuori dallo stack (in questo caso, il metodo go () che è ciò che vuoi). Questo è il comportamento in Visual Studio 2005; Non ho usato Visual Studio 2008, quindi non so se questo si comporti allo stesso modo in quella versione.


Ho provato questo sia in VS2005 che VS2008, ma non lo vedo davvero. Ho la finestra "Auto" aperta, ma quando nella funzione "go" la finestra dell'auto è vuota. Anche quando si esce dalla funzione (la parentesi graffa di chiusura della funzione è gialla). Puoi darmi un altro suggerimento?
doekman,

Mi aspetto che la finestra di Auto sia vuota mentre DENTRO la funzione go (). È necessario uscire COMPLETAMENTE dalla funzione (ovvero il cursore di debug dovrebbe puntare alla funzione che ha CHIAMATO go ()) e quindi si dovrebbe vedere il valore restituito per go () nella finestra Autos.
LeopardSkinPillBoxHat

@LeopardSkinPillBoxHat: non riesco a farlo funzionare, anche con il tuo suggerimento in più. Stai provando questo in Visual Basic? Sembra avere un miglior supporto per l'osservazione e la modifica dei valori di ritorno ...
Roman Starkov,

@romkyns - Cosa ti appare nella finestra "Auto"? Non mostra una linea che indica cosa ha restituito l'ultima funzione chiamata?
LeopardSkinPillBoxHat,

2
@LeopardSkinPillBoxHat: no, non lo fa in C #. PS Wow, mi ci è voluto un po 'per vederlo di nuovo.
Roman Starkov,

7

Sì, c'è un modo molto carino. Uno svantaggio significativo è che dovresti aspettare 5, forse 6 anni. Dal momento che vedo che hai pubblicato nel novembre 2008, ti suggerisco di waaaaaa ...

... aaaait. E voilà! Solo per te, MS ha rilasciato l'ultima versione di Visual Studio 2013 in cui è una funzionalità predefinita accessibile dai menu durante l'esecuzione in modalità debug (menu DebugWindowsAuto ).


@Doug Perché la domanda è stata posta nel novembre 2008 e la mia risposta è arrivata a settembre 2014. Il poster originale è probabilmente soddisfatto e non vuole spostare il merito. Ma sono d'accordo con te - non mi dispiacerebbe qualche altro problema sulla mia risposta. Mi piacciono i turbolenti e il guadagno in rep. :)
Konrad Viltersten

Ho avuto questo problema oggi. Grazie per la risposta nel 2014 anche se il numero iniziale è del 2008. La tua risposta è quello che stavo cercando.
AP

@AP Nessun problema. Sembra un po 'una macchina del tempo per vedere questo post. Scoppio dal passato, hehe.
Konrad Viltersten,

5

Esistono molte soluzioni alternative, ma nessuna sembra soddisfacente.

Per citare John Skeet di seguito (commentare una risposta ora cancellata):

Mi sembra ancora scomodo, specialmente se non sai quale valore di ritorno avrai bisogno prima di iniziare il debug. Non voglio davvero avere una variabile temporanea che ingombra il mio codice ogni volta che restituisco qualcosa

In teoria, il debugger potrebbe avere una returnvariabile. Dopotutto: è solo una variabile nello stack:

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

Quindi considera questa una richiesta di funzionalità per Visual Studio.


c'è una differenza abbastanza grande tra una variabile (un locale ben definito) e un valore nello stack. È un valore nello stack, ma non è una variabile (= locale).
Marc Gravell

@Marc: Non sono sicuro di come funzioni CLR, ma molti compilatori inseriscono argomenti di funzione nello stack sotto il puntatore dello stack (sp) e le variabili locali nello stack, sopra il puntatore dello stack. Questo è proprio quello che sto cercando di mostrare. E OK, quando il valore restituito è un tipo di riferimento, ottieni solo un valore del puntatore.
doekman,

1
Non è necessariamente in pila. In effetti, se visualizzi Debug -> Registri, puoi vederlo in EAX
Mark Sowul,

5

Volevo espandere la risposta di PascalK per farlo funzionare in Visual Studio 2015, perché esiste una funzionalità nascosta che non è documentata in Esamina i valori restituiti delle chiamate di metodo .

Se hai chiamate di funzione nidificate, le pseudo-variabili $ResultValueXvengono create automaticamente, dove la X si riferisce all'ordine di chiamata della funzione. Quindi, se hai una chiamata come Multiply(Five(), Six()), vengono create le seguenti pseudo-variabili:

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

2

Microsoft Visual C ++ era solito farlo, ma Visual Studio non ha AFAIK .. :(


2

L'unico modo che conosco è posizionare un punto di interruzione sulla linea di ritorno e quindi chiamare la finestra Quick Watch e inserire l'espressione restituita:

someTableAdapter.getSomeData();

Ma questo funziona solo se la chiamata non cambia lo stato di alcun oggetto (poiché ci sarà una seconda chiamata allo stesso metodo quando riprenderai l'esecuzione).


5
Questo funziona anche solo se la tua espressione non ha lambda.
Roman Starkov,

1

Puoi anche chiedere di valutare il valore anche nella finestra intermedia, se non imposta flag o altre variabili, ma restituisce solo qualcosa.


Devi includere la lambda nella domanda, poiché uso troppo spesso la finestra immediata
Chris S

1

Penso che sia possibile determinarlo guardando il registro RAX nella finestra Registri (Debug / Windows / Registri). Dopo essere usciti (MAIUSC + F11) della funzione, controllare il registro RAX. Non lo so per certo, ma una volta sulla luna potresti controllare un registro (giorni precedenti .NET) e vedere il valore di ritorno lì. Potrebbe anche essere una combinazione di RAX e RBX, ecc.


1

L'apertura della finestra Debug → Auto ti avvicina. Non mostrerà il valore restituito effettivo, ma mostrerà ciò che è stato valutato nell'istruzione return.


2
Impossibile ottenere la finestra delle auto VS2008 per mostrare qualcosa del genere. Potresti chiarire, per favore?
Roman Starkov,

return x + y; Quello che intendevo era se imposti un punto di interruzione su questa linea, quindi la finestra Debug-Auto mostrerà i valori correnti per xey. Come ho detto, ti avvicini solo. Sto solo cercando di essere d'aiuto. Non credo che meriti un voto negativo.
GeekyMonkey,

1

Sì, passando a VB.NET. ; P (Hai appena detto "Visual Studio".;)

Per quanto ricordo (da Visual Basic a tutte le versioni di VB.NET), puoi semplicemente interrogare il nome della funzione. "Funziona" come una variabile locale che è implicitamente dichiarata all'inizio della funzione e il suo valore corrente è anche usato come valore di ritorno ogni volta che la funzione esce tramite mezzi di dichiarazione non-return (es.Exit Function o semplicemente fallendo) e, naturalmente, quando viene utilizzata l'istruzione return.

È inoltre impostato sull'espressione dell'istruzione return. Proprio come una variabile locale, il suo valore può essere ispezionato in qualsiasi punto di esecuzione all'interno della funzione (anche dopo l'esecuzione dell'istruzione return). C # non ha questo e dovrebbe.

Quella piccola funzionalità VB.NET (oltre Exit Functionall'affermazione che abilita - un'altra funzione che C # non ha e dovrebbe) è molto utile in una forma di programmazione difensiva che pratico in cui inizializzo sempre il nome della funzione sul valore di errore / predefinito come prima affermazione. Quindi, in qualsiasi punto di errore (che di solito si verifica molto più spesso dei punti di successo), posso semplicemente chiamare l' Exit Functionistruzione (cioè senza dover duplicare l'espressione di errore / default o anche un nome costante / variabile).


1

La risposta accettata non funziona correttamente con Visual Studio 2015, ma posizionando un punto di interruzione sull'ultima riga del metodo e premendo F10, inserirà tutte le espressioni del valore restituito nella finestra dei locali.


Probabilmente puoi anche modificare la risposta accettata per includere i tuoi commenti.
doekman,

0

Puoi provare a selezionare "someTableAdapter.getSomeData();", fai clic destro su di esso e vai a Quick Watch .


-1

Trascina e rilascia l'espressione di ritorno in una finestra di controllo.

Ad esempio, nell'istruzione

return someTableAdapter.getSomeData();

trascinare e rilasciare

someTableAdapter.getSomeData()

in una finestra di controllo e vedrai il valore.

Puoi farlo per qualsiasi espressione.


2
Il problema è che: l'espressione viene valutata due volte.
doekman,

6
E guardare le espressioni non può contenere espressioni lambda, che uso un po '.
Steve Crane,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.