446

Take the following function:

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

When I set a breakpoint in this function, is there a possibility to inspect the returned value? go() is directly coupled to a datagrid in an .aspx page.

The only way to inspect the returned datatable is to use a temporary variable. However, that's a bit inconvenient. Isn't there another way?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
doekman
  • 18,750
  • 20
  • 65
  • 86
  • 2
    You can add a watch if you move back up the call stack – Chris S Sep 06 '10 at 14:42
  • You used to be able to do this in VB6, I seem to remember. But back then the syntax for functions involved setting the function's value to the return value... – Neil Barnwell Oct 25 '10 at 12:19
  • 5
    Comment for Visual C++ users: Type $ReturnValue in the Immediate Window or the Watch Window. At least on my VS 2010 it worked! – sergiol Sep 30 '13 at 13:03
  • 11
    For VS2015 use $ReturnValue1 .. incase you dont want to read through the 20 answers and 100 comments below! – felickz Apr 20 '16 at 22:53
  • 7
    What's the 2019 answer to all of this? These answers are super dated. – dylanh724 May 02 '19 at 08:33
  • Visual Studio 2019 for Mac doesn't seem to have anything (I don't see auto's window, and the watch for `$ReturnValue` doesn't give a vaule). – doekman May 28 '19 at 13:05
  • @dylanh724 While debugging C# managed code, `$ReturnValue` will display the result only _immediately after_ stepping out of a function. – Suncat2000 Jun 17 '20 at 12:54
  • @dylanh724 In Visual Studio 2019 you need to check for $ReturnValue in Immediate Window (just execute that) JUST AFTER leaving the method / function. It works also in Watch window. – Marcin Sep 02 '21 at 13:16

21 Answers21

320

Not that I know of. Note that if you do add a variable, it will get removed by the compiler in release builds anyway...

Update: This functionality has been added to VS2013. You can see the return values in the autos windows or use $ReturnValue (or $ReturnValue1 or $returnvalue, depending on the VS version) in the watch/immediate window.

The value can only be seen directly after returning from the function, thus the easiest way to access it is by putting a breakpoint on the function call and step over (F10) the call.


Update for VS2015: boo! unfortunately, it doesn't appear to be in VS2015 (devenv v14)
Update for VS2017: it's back. (devenv v15)

Ben Jasperson
  • 300
  • 4
  • 17
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 13
    The reason to forgo the temp is readability & style, not efficiency, no? – orip Jul 26 '10 at 13:29
  • 2
    @orip there are various reason not to modify the code, such as; it's not your code, it's a one off debug and stepping through again will take a long time. (that's why I looked up this question anyway :-) – Myster Aug 16 '12 at 02:57
  • 8
    It is possible since VS 2010 with IntelliTrace: http://blogs.msdn.com/b/habibh/archive/2009/10/23/using-intellitrace-to-view-the-return-value-of-a-vb-or-c-method.aspx – Daniel Hilgarth Oct 28 '12 at 12:53
  • 2
    Intellitrace is just available in VS Ultimate Edition. – JMGH Jan 23 '14 at 20:56
  • 3
    @MarcGravell Your answer is **wrong**! Sure, it took me six years between your reply and MS releasing that feature in VS13, but still. If you'd only had added "*for the time being*" as a disclaimer... (No, I'm not retarded. It **is** a joke, of course. You're godlike, mate.) – Konrad Viltersten Sep 03 '14 at 12:32
  • 6
    @MarcGravell for VS2015: $ReturnValue1 works! (tested in ultimate version) – G.Y Apr 01 '16 at 20:46
  • @G.Y I get "error CS0103: The name '$ReturnValue1' does not exist in the current context" - what update is yours? – Marc Gravell Apr 01 '16 at 21:36
  • @MarcGravell Microsoft Visual Studio Enterprise 2015 Version 14.0.24720.00 Update 1, You must reach the breakpoint and then press F10, if you put the break point after the "return" - you'll get the error you mentioned. – G.Y Apr 01 '16 at 22:20
  • 1
    @G.Y I think you're trying to april fools me... doesn't work :/ – Marc Gravell Apr 01 '16 at 22:42
  • @MarcGravell you helped me in the past if I am not mistaken - I wouldn't waste your time. Today - 3rd of April.. it still works. – G.Y Apr 03 '16 at 01:23
  • I don't get it - I tried today - same app, same IDE - and it didn't work.. I am not sure what is going on.. it did work in different area while debugged. – G.Y Apr 07 '16 at 09:56
  • 2
    See my answer for VS2015 support – PascalK Apr 14 '16 at 13:17
  • @PascalK None of the solutions works for me... cannot see any `$ReturnValue`/`$ReturnValue1` (Microsoft Visual Studio Professional 2015, Version 14.0.25123.00 Update 2, C# Project .NET 4.5.2) – joerg Apr 21 '16 at 10:17
  • 1
    I've had success with $ReturnValue1 in VS2015 Version 14.0.25123.00, Update 2. Note: I added a breakpoint *before* the return statement and added $ReturnValue1 value to my Watch window. Then when my breakpoint was hit and I stepped over the code (F10), the value in the Watch window changes to the return value *after* the return statement has been executed. – pb. May 27 '16 at 14:27
  • 3
    Here is link to documentation on `$ReturnValue1` support - https://msdn.microsoft.com/en-us/library/dn323257.aspx – Alexei Levenkov May 30 '16 at 19:20
  • 1
    On VS 2015 Update 3 both `$ReturnValue` and the autos window appear to work by default. **However**, the return value does not appear to show up *anywhere* if you have the `Use Managed Compatibility Mode` debugging option enabled (a global option, not per-project), so check that if you still do not see it in VS 2015. – Nick Sep 13 '16 at 20:56
  • 1
    Indeed, as @Nick has mentioned, `$ReturnValue` works only if `Use Managed Compatibility Mode` is not checked (Tools>Options>Debugging>General). However, one thing to point is that `$ReturnValue` is available for the current method only and immediately after you step out of the method (or it shows the value returned by the currently stepped over statement, if applicable). – Vladislav Aug 29 '17 at 11:03
  • I just checked a variable like $ReturnValue in Watch window right after a return statement and it showed proper info. (VS 2015 Professional Update 3) Can anyone else back this up? – Iulian Ilies Nov 02 '17 at 20:31
  • Doesn't appear to be in VS2017 either... unless it is implemented some other way – Joe Phillips Jun 06 '18 at 22:03
  • 1
    Confirmed working on VS2017 Professional v15.7.4. I set `$ReturnValue` in the watch window and after hitting F10 to return to call, that property was set to true or false depending on the lambda item from a list. – Ben Sewards Aug 23 '18 at 21:31
  • 6
    I'll point out that in VS2019 (at least), the intellisense suggests $returnvalue all lowercase. It is case sensitive however. – Mike Cheel Feb 08 '21 at 19:40
  • 2
    @MarcGravell it's $returnvalue (all lowercase) on VS2019. $ReturnValue no longer works. – Ryan Shripat Sep 22 '21 at 15:35
  • 3
    .NET 6 / VS 2022: Seems not to be working (neither Auto-Window nor $ReturnValue/$ReturnValue1/$returnvalue in Watch)... – MHolzmayr Sep 21 '22 at 08:14
  • 2
    In Visual Studio 2022 the name $ReturnValue in watch window works, but it needs to be added to the watch window BEFORE "return" statement is hit, not after. – andrew.fox Feb 08 '23 at 11:24
57

This can be done in Visual Studio 2013 with CLR 4.5.1 according to the customer feedback site. It was not available in previous versions for C#.

(Visual Studio 2008 and earlier supported it for VB.NET. It has always been available to C/C++ developers.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alex Angas
  • 59,219
  • 41
  • 137
  • 210
  • 1
    How do you do this in Visual Studio 2010 C++? – User Sep 19 '11 at 13:05
  • Microsoft Connect says there is a fundamental issue with managed code that prevents implementing this in a reliable manner: – Dan Solovay Jun 17 '12 at 14:28
  • @DanSolovay The words they use are "we couldn't do the right thing consistently" (for VS11) but they "want to bring this back" and "are looking at a number potential solutions to this problem". – Alex Angas Jun 21 '12 at 02:22
  • The connect entry is stale. The feature seems to be ... abandoned :((( – Softlion Sep 24 '12 at 05:49
  • 1
    It is possible since VS 2010 with IntelliTrace: http://blogs.msdn.com/b/habibh/archive/2009/10/23/using-intellitrace-to-view-the-return-value-of-a-vb-or-c-method.aspx – Daniel Hilgarth Oct 28 '12 at 12:54
  • “As just one example, .NET developers have been asking for a feature that’s been available to C++ developers for a while: viewing method return values in the debugger, even if those values are never stored into any declared variable. With .NET 4.5.1 and Visual Studio 2013, this capability is now built-in.” http://thejohnsmithblog.wordpress.com/2013/06/26/vs2013-and-net4-5-1-preview/ – Ross Buggins Dec 09 '13 at 10:57
26

I agree that this is a very useful thing to have: not only seeing the return value of the method before stepping out of it, but also seeing the return value of methods I just stepped over. I implemented it as part of a commercial extension to Visual Studio called "OzCode".

With it, you can view method return values right on the code editor, as sort of a HUD-display:

Statement Visualization

For more information, please see this video.

Dror Helper
  • 30,292
  • 15
  • 80
  • 129
Omer Raviv
  • 11,409
  • 5
  • 43
  • 82
  • Looks great, but 100 dollar _per year_ for the Visual Studio Extension is really too much for private users. For companies this can be different. – Beauty Aug 31 '21 at 09:54
24

According to Microsoft, there is no way to implement this reliably with managed code. This is a problem they are aware of and are working on:

For those out there who have experience debugging native C++ or VB6 code, you may have used a feature where function return values are provided for you in the Autos window. Unfortunately, this functionality does not exist for managed code. While you can work around this issue by assigning the return values to a local variable, this is not as convenient because it requires modifying your code. In managed code, it’s a lot trickier to determine what the return value of a function you’ve stepped over. We realized that we couldn’t do the right thing consistently here and so we removed the feature rather than give you incorrect results in the debugger. However, we want to bring this back for you and our CLR and Debugger teams are looking at a number potential solutions to this problem. Unfortunately this is will not be part of Visual Studio 11.

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

Dan Solovay
  • 3,134
  • 3
  • 26
  • 55
23

Regarding Visual Studio 2015:

According to the currently accepted answer by Marc Gravell:

This functionality has been added to Visual Studio 2013. You can see the return values in the autos windows or use $ReturnValue in the watch/immediate window

That answer also stated that this functionality does not work in Visual Studio 2015. This is not (entirely) true. On Examine return values of method calls there is the following note:

You must have the legacy expression evaluators turned on for $ReturnValue to be recognized (Tools / Options / Debugging / Use the legacy C# and VB expression evaluators). Otherwise, you can use $ReturnValue1.

I tested this in Visual Studio 2015 Enterprise:

  • With legacy expression evaluators turned off: only $ReturnValue1 works
  • With legacy expression evaluators turned on: both $ReturnValue and $ReturnValue1 work
StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
PascalK
  • 311
  • 2
  • 4
  • 3
    This no longer appears to be necessary. On VS 2015 Update 3, I have legacy evaluators disabled and `$ReturnValue` works. However, the return value does not appear anywhere if you have the `Use managed compatibility mode` debugging option enabled. – Nick Sep 13 '16 at 20:54
13

If you go to menu ToolsOptions, IntelliTrace, and change the setting to collect events and call information.

You can go back to the previous call event (Ctrl + Shift + F11) and see the temporary value returned from the method call in the autos window as a child of the method name.

This isn't showing you the return value for the method you are in. It just shows you the return value of the last method called in the current method.

So, it's fine for

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

as it shows you the return value for someTableAdapter.getSomeData().

But not for:

int go(){return 100 * 99;}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ross Buggins
  • 195
  • 1
  • 11
12

Old trick from the pre .NET days: Open the Registers window and look at the value of the EAX register. This contains the return value of the last function called.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ColinM
  • 388
  • 3
  • 10
  • 1
    +1 for old school closer to the metal approach - this will, however, not work for all return values (and it's up to the JIT'er, obviously - who knows what crazy optimization it might decide on that won't use EAX?). For integral types it will (mostly?) work. Large value types are a different matter (and as far as I recall from some blog post, those won't be displayed in VS2013 either). – JimmiTh Aug 10 '13 at 02:12
11

Step out of the go() method using Shift-F11, and then in the "Autos" debug window it will show the return value of the method call which just popped off the stack (in this case, the go() method which is what you want). This is the behaviour in Visual Studio 2005; I haven't used Visual Studio 2008 so I don't know if this behaves the same way in that version.

LeopardSkinPillBoxHat
  • 28,915
  • 15
  • 75
  • 111
  • I've tried this in both VS2005 and VS2008, but I don't really see it. I have the "Autos" window open, but when in the "go" function, the autos-window is just empty. Also when stepping out of the function (the closing curly brace of the function is yellow). Can you give me one more hint? – doekman Nov 06 '08 at 10:32
  • I would expect the Autos-window to be empty while INSIDE the go() function. You need to step COMPLETELY OUT of the function (i.e. the debug cursor should be pointing to the function which has CALLED go()) and then you should see the return value for go() in the Autos window. – LeopardSkinPillBoxHat Nov 06 '08 at 10:39
  • @LeopardSkinPillBoxHat: can't get this to work, even with your extra hint. Are you trying this in Visual Basic? It appears to have better support for observing and changing return values... – Roman Starkov Nov 18 '09 at 17:41
  • @romkyns - What shows up in the "Autos" window for you? Doesn't it show a line indicating what the last called function returned? – LeopardSkinPillBoxHat Nov 19 '09 at 00:22
  • 2
    @LeopardSkinPillBoxHat: no, it doesn't do that in C#. P.S. Wow, took me a while to see this again. – Roman Starkov Apr 30 '10 at 20:43
7

Yes, there is a very nice way. One significant drawback is that you'd have to wait for 5, maybe 6 years. Since I see that you posted in November 2008, I suggest that you waaaaaa...

...aaaait. And voilà! Just for you, MS has released the latest Visual Studio 2013 where it's a default feature accessible from the menus while running in debug mode (menu DebugWindowsAutos).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
  • @Doug Because the question was asked November 2008 and my reply came September 2014. The original poster is probably satisfied and doesn't want to move the credit. But I do agree with you - I wouldn't mind a few more upsies on my answer. I like upsies and rep gain. :) – Konrad Viltersten Apr 06 '17 at 06:33
  • Had this issue today. Thanks for replying in 2014 even though the initial issue is of 2008. Your answer is what I was looking for. – A.P. May 17 '17 at 15:36
  • @A.P. No problems. Feels a bit like a time machine to see this post. Blast from the past, hehe. – Konrad Viltersten May 18 '17 at 12:36
5

I wanted to expand upon PascalK's answer for getting this to work in Visual Studio 2015, because there is a hidden feature which is not documented in Examine return values of method calls.

If you have nested function calls, the pseudo-variables $ResultValueX are automatically created, where the X refers to the function call order. So if you have a call such as Multiply(Five(), Six()), the following pseudo-variables are created:

Five()     | $ResultValue1 = 5
Six()      | $ResultValue2 = 6
Multiply() | $ResultValue3 = 30
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
splttingatms
  • 341
  • 3
  • 9
5

There are a lot of workarounds, but none seems satisfactory.

To quote John Skeet below (comment on a now-deleted answer):

Still looks inconvenient to me - especially if you don't know which return value you're going to need before you start debugging. I really don't want to have to have a temporary variable cluttering up my code every time I ever return anything.t

In theory, the debugger could have a return-variable. After all: it's just a variable on the stack:

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

So consider this a feature request for Visual Studio.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
doekman
  • 18,750
  • 20
  • 65
  • 86
  • there's quite a big a difference between a variable (a well-defined local) and a value on the stack. It is a value on the stack, but it isn't a variable (=local). – Marc Gravell Jun 06 '10 at 19:09
  • @Marc: I'm not sure how the CLR works, but a lot of compilers put function arguments on the stack below the stack pointer (sp), and local variables on the stack, above the stack pointer. That is just what I'm trying to show. And OK, when the return value is a reference type, you just get some pointer value. – doekman Mar 30 '11 at 09:36
  • 1
    It's not necessarily on the stack. In fact, if you view Debug -> Registers you're apt to see it in EAX – Mark Sowul Nov 18 '11 at 15:40
4

In VS2019, Just go to Debug->Windows->Autos window. There, you see concat return value as shown below:

enter image description here

BHP
  • 443
  • 4
  • 13
2

Microsoft Visual C++ used to do this, but Visual Studio doesn't AFAIK.. :(

Sprintstar
  • 7,938
  • 5
  • 38
  • 51
2

The only way I know is to place a breakpoint on the return line and then call the Quick Watch window and enter the returned expression:

someTableAdapter.getSomeData();

But this only works if the call does not change the state of any object (since there will be a second call to the same method when you will resume the execution).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sylvain Rodrigue
  • 4,751
  • 5
  • 53
  • 67
1

I think you can determine this by looking at the RAX register in the Registers window (Debug / Windows / Registers). After stepping out (SHIFT + F11) of the function, check the RAX register. I don't know for a fact, but once upon a moon you could check a register (pre .NET days) and see the return value there. It might even be a combination of RAX and RBX, etc.

Joe Rattz
  • 319
  • 1
  • 5
  • 13
1

Yeah, by switching to VB.NET. ;P (You did just say "Visual Studio". ;)

For as long as I can remember (from Visual Basic through all versions of VB.NET), you can simply query the function name. It "functions" like a local variable that's implicitly declared at the start of the function and its current value is also used as the return value whenever the function exits via non-return statement means (i.e. Exit Function or just falling through) and of course, when the return statement is used.

It is also set to the return statement's expression. Just like a local variable, its value can be inspected at any point of execution inside the function (including after the return statement is executed). C# doesn't have this and should.

That little VB.NET feature (plus the Exit Function statement which it enables - another feature C# doesn't have and should) is very useful in a form of defensive programming I practice where I always initialize the function name to the failure/default value as the first statement. Then, at any failure point (which normally occurs much more often than success points), I can simply call the Exit Function statement (i.e. without having to duplicate the failure / default expression or even a constant/variable name).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tom
  • 870
  • 11
  • 13
1

You can also ask to evaluate the value in the intermediate window as well, if it does not set flags or other variables, but only returns something.

Biri
  • 7,101
  • 7
  • 38
  • 52
1

Opening the Debug → Autos window gets you close. It won't show the actual return value, but it will show what was evaluated in the return statement.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
GeekyMonkey
  • 12,478
  • 6
  • 33
  • 39
  • 2
    Couldn't get VS2008 autos window to show anything like that. Could you please clarify? – Roman Starkov Nov 18 '09 at 17:40
  • `return x + y;` What I meant was if you set a breakpoint on this line, then your Debug-Autos window will display the current values for x and y. As I said, it only get's you close. Just trying to be helpful. I don't think that deserves a downvote. – GeekyMonkey Nov 21 '11 at 16:25
1

The accepted answer doesn't work properly with Visual Studio 2015, but by placing a break point on the last line of the method and pressing F10, it will put all expressions of the return value into the locals window.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Esben Skov Pedersen
  • 4,437
  • 2
  • 32
  • 46
0

You could try to select "someTableAdapter.getSomeData();", right click on it, and go for Quick Watch.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Yann Semet
  • 623
  • 2
  • 5
  • 12
0

Drag and drop the return expression into a watch window.

For example, in the statement

return someTableAdapter.getSomeData();

drag and drop

someTableAdapter.getSomeData()

into a watch window, and you'll see the value.

You can do this for any expression.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Pita.O
  • 1,864
  • 1
  • 19
  • 27