在使用Visual Studio进行调试时,我能否在返回之前找到返回值?

451

考虑以下函数:

DataTable go() {
    return someTableAdapter.getSomeData();
}
当我在这个函数中设置一个断点时,有没有可能检查返回值?go()直接与.aspx页面中的datagrid相耦合。检查返回的datatable的唯一方法是使用临时变量。不过,那有点不方便。还有其他方法吗?

2
如果你回到调用堆栈的上方,你可以添加一个监视器。 - Chris S
5
针对Visual C++用户的注释:在“立即窗口”或“监视窗口”中输入$ReturnValue。至少在我的VS 2010上有效! - sergiol
11
如果您不想阅读下面的20个答案和100条评论,请使用$ReturnValue1来使用VS2015! - felickz
7
这个问题的2019年答案是什么?这些回答已经过时了。 - dylanh724
@dylanh724 在Visual Studio 2019中,你需要在方法/函数结束后立即检查Immediate Window中的$ReturnValue(只需执行即可)。它也适用于Watch窗口。 - Marcin
显示剩余3条评论
21个回答

322

我不知道有没有这样的功能。请注意,如果您添加了一个变量,在发布版本中编译器会将其删除...

更新: VS2013已经添加了此功能。 您可以在自动窗口中查看返回值,或者在监视/立即窗口中使用$ReturnValue(或$ReturnValue1$returnvalue,具体取决于VS版本)。

该值只能在从函数返回后直接查看,因此访问它最简单的方法是在函数调用上设置断点并跨过(F10)调用。


VS2015更新:糟糕!不幸的是,它似乎不在VS2015中(devenv v14)
VS2017更新:它回来了。(devenv v15)


13
放弃使用临时变量是为了提高可读性和风格,而不是为了提高效率,对吧? - orip
8
自2010年起,通过使用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
3
@MarcGravell 您的回答是错误的!确实,在您回复后六年,微软才在VS13中发布了该功能,但仍然如此。如果您只是添加了“暂时”作为免责声明...(不,我并不愚笨。这当然是一个玩笑。您很厉害,伙计。) - Konrad Viltersten
6
@MarcGravell 对于VS2015:$ReturnValue1有效!(在旗舰版中测试过) - G.Y
6
我会指出,在VS2019中(至少是这样),Intellisense建议使用小写的"$returnvalue"。但它是区分大小写的。 - Mike Cheel
显示剩余19条评论

57
这可以在带有CLR 4.5.1的Visual Studio 2013中完成,根据客户反馈网站的说法。之前的C#版本不支持此功能。(对于VB.NET,Visual Studio 2008及更早版本支持此功能。 对于C / C ++开发人员,一直可用。)

1
在Visual Studio 2010 C++中,你如何做到这一点? - User
Microsoft Connect 表示,托管代码存在根本性问题,无法以可靠的方式实现此操作。 - Dan Solovay
@DanSolovay 他们使用的词是“我们无法始终做正确的事情”(针对VS11),但他们“想要恢复这一点”,并且“正在寻找许多潜在的解决方案来解决这个问题”。 - Alex Angas
连接条目已过期。这个功能似乎被...抛弃了 :((( - Softlion
1
自VS 2010以来,使用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
仅举一个例子,.NET开发人员一直在要求一项功能,这个功能已经提供给C++开发人员一段时间了:即使这些值从未存储到任何声明的变量中,也可以在调试器中查看方法返回值。通过.NET 4.5.1和Visual Studio 2013,现在已经内置了这种能力。 - Ross Buggins

26

我认为这是一个非常有用的工具:它不仅可以在退出方法之前查看方法的返回值,还可以查看已经跳过的方法的返回值。 我将其作为 Visual Studio 的商业扩展实现,名为“OzCode”。

使用它,您可以在代码编辑器中直接查看方法的返回值,就像 HUD 显示一样:

Statement Visualization

有关更多信息,请参见此视频


看起来很不错,但对于个人用户来说,每年100美元的Visual Studio扩展费用确实太高了。对于公司来说可能会有所不同。 - Beauty

25
据微软公司称,使用托管代码无法实现这一点的可靠性,他们已经意识到这个问题并正在努力解决:
对于那些有经验调试本机C++或VB6代码的开发者,你们可能使用过一个功能,即在“自动”窗口中为你提供函数返回值。不幸的是,托管代码中不存在此功能。虽然您可以通过将返回值分配给本地变量来解决此问题,但这种方法并不方便,因为它需要修改您的代码。 在托管代码中,确定您跨越的函数的返回值就要棘手得多。我们意识到我们不能在这里始终做正确的事情,所以我们取消了这个特性,而不是在调试器中给您不正确的结果。然而,我们想为您带回这个功能,我们的CLR和调试器团队正在研究解决这个问题的许多潜在解决方案。不幸的是,这不会成为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
根据@Alex的回答(https://dev59.com/x3VC5IYBdhLWcg3whRcw#3714884),这在VS2013与CLR 4.5中可用。 - Dan Solovay

23

关于Visual Studio 2015:

根据Marc Gravell目前被接受的答案:

这个功能已经添加到Visual Studio 2013中。您可以在自动窗口中查看返回值,或者在监视/立即窗口中使用$ReturnValue。

该答案还指出,此功能在Visual Studio 2015中无法使用。这不是完全正确的。在检查方法调用的返回值中有以下说明:

您必须启用遗留表达式评估器才能识别$ReturnValue (工具/选项/调试/使用遗留C#和VB表达式评估器)。否则,您可以使用$ReturnValue1

我在Visual Studio 2015 Enterprise中进行了测试:

  • 如果关闭了传统的表达式求值器: 只有 $ReturnValue1 有效。
  • 如果启用了传统的表达式求值器: 两个 都有效,即 $ReturnValue $ReturnValue1

3
不必要了。在VS 2015 Update 3上,我已经禁用了旧的评估器,并且"$ReturnValue"可用。但是,如果启用了“使用托管兼容性模式”调试选项,则返回值不会出现在任何地方。 - Nick

13
如果您转到菜单 工具选项,选择 IntelliTrace,并更改设置以收集事件和调用信息。
您可以回到先前的调用事件(Ctrl + Shift + F11),并在自动窗口中查看作为方法名称的子项返回的临时值。
这并不会显示您所在方法的返回值。它只显示当前方法中最后一个被调用的方法的返回值。
因此,对于...
DataTable go(){return someTableAdapter.getSomeData();}

因为它会展示给你someTableAdapter.getSomeData()的返回值。

但不包括:

int go(){return 100 * 99;}

12

从 .NET 之前的老技巧:打开寄存器窗口并查看 EAX 寄存器的值。这个寄存器包含了上一个调用函数的返回值。


1
+1 给老派的更接近底层的方法 - 然而,这并不适用于所有返回值(显然由JIT'er决定 - 谁知道它可能会决定使用EAX的什么疯狂优化?)。对于整数类型,它将(大多数情况下?)有效。大型值类型是另一回事(据我所记得的某篇博客文章,这些类型在VS2013中也不会显示)。 - JimmiTh

11

使用Shift-F11键退出go()方法,然后在“Autos”调试窗口中,它将显示刚从堆栈中弹出的方法调用的返回值(在本例中,这是您想要的go()方法)。这是Visual Studio 2005中的行为;我没有使用过Visual Studio 2008,所以不知道该版本是否以相同方式运行。


我已经在VS2005和VS2008两个版本上尝试了,但是并没有看到。我的“Autos”窗口是打开的,但当进入“go”函数时,它是空的。同样,当从函数中跳出时(函数的右大括号是黄色的),也是如此。你能再给我一条提示吗? - doekman
我希望在 go() 函数内部时 Autos 窗口为空。您需要完全退出该函数(即,调试光标应指向调用 go() 的函数),然后您应该在 Autos 窗口中看到 go() 的返回值。 - LeopardSkinPillBoxHat
@LeopardSkinPillBoxHat:即使有你的额外提示,我也无法让它正常工作。你是在尝试使用Visual Basic吗?它似乎对于观察和更改返回值有更好的支持... - Roman Starkov
@romkyns - 你的“自动”窗口显示了什么?它没有显示最后调用函数返回的行吗? - LeopardSkinPillBoxHat
2
@LeopardSkinPillBoxHat:不,C#不会这样做。顺便说一句,哇,我花了很长时间才再次看到这个。 - Roman Starkov

7
是的,有一种非常好的方法。一个重要的缺点是,你可能需要等待5年,甚至6年。由于我看到你在2008年11月发布了这篇文章,所以建议你等待一下。嗯!就为你推出了最新的Visual Studio 2013,其中它是在调试模式下的默认功能,在菜单Debug→Windows→Autos中可以访问到。

@Doug 因为这个问题是在2008年11月提出的,而我的回复是在2014年9月发表的。原帖作者可能已经满意并且不想转移信用。但我同意你的观点 - 我不介意我的答案再得到一些赞和声望。我喜欢赞和声望。 :) - Konrad Viltersten
今天遇到了这个问题。感谢您在2014年回复,尽管最初的问题是2008年的。您的答案正是我正在寻找的。 - A.P.
@A.P. 没问题。看到这篇文章感觉有点像时光机。哈哈,过去的回忆。 - Konrad Viltersten

5
我希望您能扩展PascalK的答案,以在Visual Studio 2015中使其正常工作,因为有一个未记录在检查方法调用的返回值中的隐藏功能。
如果您有嵌套的函数调用,则会自动创建伪变量$ResultValueX,其中X指函数调用顺序。因此,如果您有这样的调用Multiply(Five(), Six()),则会创建以下伪变量:
Five()     | $ResultValue1 = 5
Six()      | $ResultValue2 = 6
Multiply() | $ResultValue3 = 30

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接