Могу ли я узнать возвращаемое значение перед возвратом во время отладки в Visual Studio?


387

Возьмите следующую функцию:

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

Когда я устанавливаю точку останова в этой функции, есть ли возможность проверить возвращаемое значение? go()напрямую связан с сетью данных на .aspxстранице.

Единственный способ проверить возвращаемую таблицу данных - использовать временную переменную. Однако это немного неудобно. Разве нет другого пути?


1
Вы можете добавить часы, если переместитесь обратно вверх по стеку вызовов
Крис С

Я имел обыкновение делать это в VB6, я помню. Но тогда синтаксис для функций включал установку значения функции в возвращаемое значение ...
Нил Барнвелл

5
Комментарий для пользователей Visual C ++: введите $ ReturnValue в окне «Немедленно» или в окне «Просмотр». По крайней мере, на моем VS 2010 это работало!
sergiol

9
Для VS2015 используйте $ ReturnValue1 .. в случае, если вы не хотите читать 20 ответов и 100 комментариев ниже!
felickz

3
Какой ответ на все это в 2019 году? Эти ответы являются устаревшими.
dylanh724

Ответы:


265

Не то, что я знаю из. Обратите внимание , что если вы делаете добавить переменный, она удаляется компилятором в освобождении строит все равно ...

Обновление: эта функциональность была добавлена ​​в VS2013 . Вы можете увидеть возвращаемые значения в окнах autos или использовать $ReturnValueв окне watch / немедленное.

Значение можно увидеть только сразу после возврата из функции, поэтому самый простой способ получить к нему доступ - это поставить точку останова на вызов функции и перешагнуть (F10) вызов.


Обновление для VS2015: бу! к сожалению, его нет в VS2015 (devenv v14)
Обновление для VS2017: он вернулся. (devenv v15)


12
Причиной отказа от темпов является удобочитаемость и стиль, а не эффективность, нет?
orip

2
@orip есть разные причины не изменять код, такие как; это не ваш код, это один из отладочных и повторный шаг займет много времени. (вот почему я все равно поднял этот вопрос :-)
Myster

8
Это возможно начиная с VS 2010 с IntelliTrace: blogs.msdn.com/b/habibh/archive/2009/10/23/…
Даниэль Хилгарт,

3
@MarcGravell Ваш ответ неверный ! Конечно, мне потребовалось шесть лет между вашим ответом и MS выпуском этой функции в VS13, но все же. Если бы вы только добавили « на данный момент » в качестве заявления об ограничении ответственности ... (Нет, я не умственно отсталый. Конечно , это шутка. Вы богоподобны, приятель.)
Конрад Вилтерстен,

6
@MarcGravell для VS2015: $ ReturnValue1 работает! (проверено в окончательной версии)
GY

58

Это можно сделать в Visual Studio 2013 с CLR 4.5.1 в соответствии с сайтом отзывов клиентов. . Это не было доступно в предыдущих версиях для C #.

(Visual Studio 2008 и более ранние версии поддерживали его для VB.NET. Он всегда был доступен для разработчиков на C / C ++.)


1
Как вы делаете это в Visual Studio 2010 C ++?
Пользователь

Microsoft Connect говорит, что есть фундаментальная проблема с управляемым кодом, которая мешает надежно реализовать это:
Дэн Соловай

@DanSolovay Используемые ими слова: «мы не могли последовательно делать правильные вещи» (для VS11), но они «хотят вернуть это назад» и «смотрят на ряд потенциальных решений этой проблемы».
Алекс Ангас

Запись о подключении устарела. Похоже, что эта функция ... заброшена: (((
Softlion

1
Это возможно начиная с VS 2010 с IntelliTrace: blogs.msdn.com/b/habibh/archive/2009/10/23/…
Даниэль Хилгарт,

25

Я согласен, что это очень полезная вещь: не только видеть возвращаемое значение метода перед тем, как выйти из него, но и видеть возвращаемое значение методов, которые я только что перешагнул. Я реализовал это как часть коммерческого расширения для Visual Studio под названием " OzCode ».

С его помощью вы можете просматривать возвращаемые значения метода прямо в редакторе кода, как своего рода HUD-дисплей:

Визуализация оператора

Для получения дополнительной информации, пожалуйста, смотрите это видео .


23

Согласно Microsoft, нет способа надежно реализовать это с помощью управляемого кода. Это проблема, о которой они знают и над которой работают:

Для тех, у кого есть опыт отладки собственного кода C ++ или VB6, вы, возможно, использовали функцию, в которой возвращаемые значения функции предоставляются для вас в окне Autos. К сожалению, эта функция не существует для управляемого кода. Хотя вы можете обойти эту проблему, назначив возвращаемые значения локальной переменной, это не так удобно, так как требует изменения вашего кода. В управляемом коде намного сложнее определить, какое возвращаемое значение функции вы перешагнули. Мы поняли, что не можем последовательно делать правильные вещи, и поэтому удалили эту функцию, вместо того, чтобы давать вам неправильные результаты в отладчике. Тем не менее, мы хотим вернуть это вам, и наши команды CLR и Debugger рассматривают ряд потенциальных решений этой проблемы. К сожалению, это не будет частью 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 выше ( stackoverflow.com/a/3714884/402949 ), это доступно для VS2013 с CLR 4.5
Дан Соловей

21

Что касается Visual Studio 2015:

Согласно принятому в настоящее время ответу Марка Гравелла:

Эта функциональность была добавлена ​​в Visual Studio 2013 . Вы можете увидеть возвращаемые значения в окнах авто или использовать $ ReturnValue в окне просмотра / непосредственного просмотра.

В этом ответе также говорилось, что эта функциональность не работает в Visual Studio 2015. Это не совсем верно. При проверке возвращаемых значений вызовов методов появляется следующее примечание:

Для распознавания $ ReturnValue необходимо включить устаревшие средства оценки выражений (Инструменты / Параметры / Отладка / Использовать устаревшие средства оценки выражений C # и VB ). В противном случае вы можете использовать $ ReturnValue1 .

Я проверил это в Visual Studio 2015 Enterprise:

  • При отключенных средствах оценки устаревших выражений: только $ ReturnValue1 работает
  • С экспрессирующими оценщиками унаследованными включены: как $ ReturnValue и $ ReturnValue1 работой

3
Это больше не кажется необходимым. В VS 2015 Update 3 у меня отключены устаревшие оценщики, и они $ReturnValueработают. Однако возвращаемое значение нигде не появляется, если у вас Use managed compatibility modeвключена опция отладки.
Ник

13

Если вы перейдете в меню ИнструментыПараметры , IntelliTrace и измените настройку для сбора событий и информации о вызовах.

Вы можете вернуться к предыдущему событию вызова ( Ctrl+ Shift+F11 ) и увидеть временное значение, возвращаемое из вызова метода в окне autos, как дочерний элемент имени метода.

Это не показывает возвращаемое значение для метода, в котором вы находитесь. Это просто показывает возвращаемое значение последнего метода, вызванного в текущем методе.

Итак, это хорошо для

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

как это показывает вам возвращаемое значение для someTableAdapter.getSomeData().

Но не для:

int go(){return 100 * 99;}

12

Старый трюк до .NET дней: откройте окно регистров и посмотрите на значение регистра EAX. Содержит возвращаемое значение последней вызванной функции.


1
+1 для старой школы ближе к подходу с металлом - это, однако, не будет работать для всех возвращаемых значений (и это зависит от JIT'er, очевидно - кто знает, какая сумасшедшая оптимизация может решить, что не будет использовать EAX? ). Для целочисленных типов это будет (в основном?) Работать. Типы с большими значениями - это другое дело (и, насколько я помню из некоторых постов в блоге, они не будут отображаться в VS2013).
JimmiTh

10

Выйдите из метода go () с помощью Shift-F11, а затем в окне отладки «Autos» он покажет возвращаемое значение вызова метода, который только что вытолкнул из стека (в данном случае, метод go (), который является то, что ты хочешь). Это поведение в Visual Studio 2005; Я не использовал Visual Studio 2008, поэтому я не знаю, ведет себя ли это так же в этой версии.


Я пробовал это как в VS2005, так и в VS2008, но на самом деле я этого не вижу. У меня открыто окно «Autos», но когда в функции «go» окно autos просто пустое. Также при выходе из функции (закрывающая фигурная скобка функции желтая). Можете ли вы дать мне еще один совет?
Doekman

Я ожидаю, что окно Autos будет пустым, пока ВНУТРИ функцию go (). Вы должны выйти из функции полностью (т.е. курсор отладки должен указывать на функцию, которая имеет CALLED go ()), а затем вы должны увидеть возвращаемое значение для go () в окне Autos.
LeopardSkinPillBoxHat

@ LeopardSkinPillBoxHat: не могу заставить это работать, даже с вашей дополнительной подсказкой. Вы пытаетесь это в Visual Basic? Похоже, он лучше поддерживает наблюдение и изменение возвращаемых значений ...
Роман Старков

@romkyns - Что отображается в окне «Авто»? Разве он не показывает строку, указывающую, что вернула последняя вызванная функция?
LeopardSkinPillBoxHat

2
@ LeopardSkinPillBoxHat: нет, в C # этого не происходит. PS Вау, мне понадобилось время, чтобы увидеть это снова.
Роман Старков

7

Да, есть очень хороший способ. Одним существенным недостатком является то, что вам придется ждать 5, а может и 6 лет. Так как я вижу, что вы отправили в ноябре 2008 года, я предлагаю вам waaaaaa ...

... aaaait. И вуаля! Только для вас, MS выпустила последнюю версию Visual Studio 2013, где это функция по умолчанию, доступная из меню при работе в режиме отладки (меню DebugWindowsAutos ).


@Doug Потому что вопрос был задан в ноябре 2008 года, а мой ответ пришел в сентябре 2014 года. Оригинальный постер, вероятно, удовлетворен и не хочет переносить кредит. Но я согласен с тобой - я бы не возражал против еще нескольких слов в ответ на мой ответ. Мне нравятся upsies и репутация. :)
Конрад Вилтерстен

Был этот вопрос сегодня. Спасибо, что ответили в 2014 году, хотя первоначальный выпуск был в 2008 году. Ваш ответ - то, что я искал.
AP

@AP Нет проблем. Похоже на машину времени, чтобы увидеть этот пост. Взрыв из прошлого, хе-хе.
Конрад Вилтерстен

5

Есть много обходных путей, но ни один не кажется удовлетворительным.

Процитирую Джона Скита ниже (прокомментируйте удаленный сейчас ответ):

Мне все еще кажется неудобным, особенно если вы не знаете, какое возвращаемое значение вам понадобится, прежде чем начинать отладку. Я действительно не хочу иметь временную переменную, загромождающую мой код каждый раз, когда я что-либо возвращаю.

Теоретически, отладчик может иметь- returnпеременную. В конце концов: это просто переменная в стеке:

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

Так что считайте это запросом функции для Visual Studio.


Существует довольно большая разница между переменной (четко определенной локальной) и значением в стеке. Это значение в стеке, но оно не является переменной (= local).
Марк Гравелл

@Marc: Я не уверен, как работает CLR, но многие компиляторы помещают аргументы функции в стек ниже указателя стека (sp), а локальные переменные в стеке выше указателя стека. Это именно то, что я пытаюсь показать. И хорошо, когда возвращаемое значение является ссылочным типом, вы просто получаете некоторое значение указателя.
doekman

1
Это не обязательно в стеке. Фактически, если вы просматриваете Debug -> Registers, вы склонны видеть его в EAX
Mark Sowul

5

Я хотел бы расширить ответ PascalK за то, чтобы заставить его работать в Visual Studio 2015, потому что есть скрытая функция, которая не документирована в проверке возвращаемых значений вызовов методов .

Если у вас есть вложенные вызовы функций, $ResultValueXавтоматически создаются псевдопеременные , где X обозначает порядок вызова функций. Поэтому, если у вас есть такой вызов Multiply(Five(), Six()), создаются следующие псевдопеременные:

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


2

Единственный способ, которым я знаю, - это поместить точку останова в строку возврата, а затем вызвать окно Quick Watch и ввести возвращаемое выражение:

someTableAdapter.getSomeData();

Но это работает только в том случае, если вызов не изменяет состояние какого-либо объекта (поскольку будет повторный вызов того же метода, когда вы возобновите выполнение).


5
Это также работает, только если ваше выражение не имеет лямбды.
Роман Старков

1

Вы также можете попросить оценить значение в промежуточном окне, если оно не устанавливает флаги или другие переменные, а только что-то возвращает.


Вам нужно включить лямбду в вопрос, так как я тоже иногда использую непосредственное окно
Chris S

1

Я думаю, что вы можете определить это, посмотрев регистр RAX в окне регистров (Debug / Windows / Registers). После выхода (SHIFT + F11) из функции проверьте регистр RAX. Я не знаю точно, но однажды вы могли бы проверить регистр (до .NET дней) и увидеть возвращаемое значение там. Это может быть даже комбинация RAX и RBX и т. Д.


1

При открытии окна «Отладка → Авто» вы закрываетесь. Он не будет отображать фактическое возвращаемое значение, но он покажет, что было оценено в операторе возврата.


2
Не удалось заставить окно VS2008 autos показывать что-либо подобное. Не могли бы вы уточнить?
Роман Старков

return x + y; Я имел в виду, что если вы установите точку останова в этой строке, то в вашем окне Debug-Autos отобразятся текущие значения для x и y. Как я уже сказал, это только приблизит тебя. Просто пытаюсь быть полезным. Я не думаю, что это заслуживает отрицательного ответа.
GeekyMonkey

1

Да, переходя на VB.NET. ; P (Вы только что сказали "Visual Studio".;)

Насколько я помню (из Visual Basic через все версии VB.NET), вы можете просто запросить имя функции. Он «функционирует», как локальная переменная, которая неявно объявляется в начале функции, и ее текущее значение также используется в качестве возвращаемого значения всякий раз, когда функция завершается с помощью средств без возврата (то есть Exit Functionили просто проваливается) и, конечно, когда оператор возврата используется.

Это также установлено в выражение оператора возврата. Как и локальная переменная, ее значение может быть проверено в любой точке выполнения внутри функции (в том числе после выполнения оператора return). C # не имеет этого и должен.

Эта небольшая функция VB.NET (плюс Exit Functionоператор, который она включает - еще одна функция C # не имеет и не должна) очень полезна в форме защитного программирования, которую я практикую, где я всегда инициализирую имя функции значением сбоя / значения по умолчанию как первое утверждение Затем в любой точке сбоя (которая обычно происходит гораздо чаще, чем точки успеха), я могу просто вызвать Exit Functionоператор (т.е. без необходимости дублировать выражение сбоя / по умолчанию или даже имя константы / переменной).


1

Принятый ответ не работает должным образом с Visual Studio 2015, но, поместив точку останова на последнюю строку метода и нажав кнопку F10, он поместит все выражения возвращаемого значения в окно локальных объектов.


Вы также можете отредактировать принятый ответ, чтобы включить ваши комментарии.
doekman

0

Вы можете попробовать выбрать "someTableAdapter.getSomeData();", щелкнуть по нему правой кнопкой мыши и перейти к Quick Watch .


-1

Перетащите возвращаемое выражение в окно просмотра.

Например, в заявлении

return someTableAdapter.getSomeData();

перетащить

someTableAdapter.getSomeData()

в окно просмотра, и вы увидите значение.

Вы можете сделать это для любого выражения.


2
Проблема с этим: выражение вычисляется дважды.
doekman

6
И часовые выражения не могут содержать лямбда-выражений, которые я использую справедливо.
Стив Крейн
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.