在使用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个回答

5
有很多解决方法,但似乎没有一个令人满意的。
引用John Skeet在下面的评论中(对现已删除的答案进行评论):
仍然对我来说看起来很不方便 - 特别是如果您在开始调试之前不知道需要哪个返回值。我真的不想每次返回任何东西时都要有一个临时变量杂乱无章地出现在我的代码中。
理论上,调试器可以有一个返回变量。毕竟:它只是堆栈上的一个变量:
unsafe {
  int * sp = stackalloc int[1];
  try {
    return a+b;
  }
  finally {
    Trace.WriteLine("return is " + *(sp+3));
  }
}

因此,将其视为Visual Studio的功能请求。


一个变量(一个定义良好的局部变量)和堆栈上的值之间存在相当大的区别。它是堆栈上的一个值,但它不是一个变量(=局部变量)。 - Marc Gravell
@Marc:我不确定CLR是如何工作的,但很多编译器会将函数参数放在堆栈指针(sp)下方的堆栈上,并将局部变量放在堆栈上方。这正是我想要展示的。当返回值是引用类型时,你只会得到一些指针值。 - doekman
1
它不一定在堆栈上。实际上,如果您查看“调试”->“寄存器”,您可能会在EAX中看到它。 - Mark Sowul

4
在VS2019中,只需转到调试->窗口->自动窗口。在那里,您可以看到如下所示的连接返回值: enter image description here

这应该是VS 2019及以上版本的被接受答案。 - Hari

2
微软的Visual C++曾经可以做到这一点,但据我所知,Visual Studio现在不行了.. :(

2

我所知道的唯一方法是在返回行上设置断点,然后调用Quick Watch窗口并输入返回的表达式:

someTableAdapter.getSomeData();

但是,这仅适用于调用不更改任何对象状态的情况(因为当您恢复执行时,将会有第二个对相同方法的调用)。


5
只有当您的表达式没有 lambda 时,这才有效。 - Roman Starkov

1

被接受的答案在使用Visual Studio 2015时无法正常工作,但是通过在方法的最后一行上设置断点并按下F10,它会将返回值的所有表达式放入本地窗口。


1

我认为您可以通过查看寄存器窗口(调试/窗口/寄存器)中的RAX寄存器来确定这一点。在步出(SHIFT + F11)函数后,请检查RAX寄存器。我不确定,但在 .NET 之前的某个时候,您可以检查寄存器并在那里查看返回值。可能甚至是RAX和RBX等的组合。


1

是的,通过转换为VB.NET。;P(你刚才说“Visual Studio”。;)

自我记忆以来(从Visual Basic到所有版本的VB.NET),您可以简单地查询函数名称。它“像”一个本地变量,在函数开始时隐式声明,并且每当函数通过非返回语句手段退出(即 Exit Function 或仅通过)并且当使用返回语句时,其当前值也用作返回值。

它还设置为返回语句的表达式。就像本地变量一样,可以在函数内的任何执行点(包括执行返回语句后)检查其值。C#没有这个功能,应该有。

我经常采用一种defensive programming的形式,即将函数名作为第一条语句初始化为失败/默认值。这时那个小巧的VB.NET功能(加上Exit Function语句的启用——这是C#没有而应该有的另一个功能)非常有用。然后,在任何失败点(通常比成功点更频繁出现),我只需调用Exit Function语句(无需重复故障/默认表达式甚至常量/变量名称)。


1

如果它不设置标志或其他变量,而只返回某些内容,您还可以要求在中间窗口中评估该值。


你需要在问题中包含lambda,因为有时我也会使用即时窗口。 - Chris S

1

打开调试→自动窗口可以让你接近目标。它不会显示实际的返回值,但它会显示在返回语句中被评估的内容。


2
无法在VS2008中显示类似的自动窗口。你能澄清一下吗? - Roman Starkov
我所指的是如果您在此行上设置断点,则调试自动窗口将显示x和y的当前值。正如我所说,它只能让您接近。只是想提供帮助。我认为这不应该被投反对票。 返回 x + y; - GeekyMonkey

0
你可以尝试选择 "someTableAdapter.getSomeData();",右键点击它,然后选择 快速查看

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