Posso descobrir o valor de retorno antes de retornar durante a depuração no Visual Studio?

387

Execute a seguinte função:

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

Quando defino um ponto de interrupção nesta função, existe a possibilidade de inspecionar o valor retornado? go()está diretamente acoplado a um datagrid em uma .aspxpágina.

A única maneira de inspecionar a tabela de dados retornada é usar uma variável temporária. No entanto, isso é um pouco inconveniente. Não existe outro caminho?

doekman
fonte
11
Você pode adicionar um relógio se você se mover de volta até a pilha de chamadas
Chris S
Você costumava fazer isso no VB6, pelo que me lembro. Mas naquela época a sintaxe para funções envolveu a criação de valor da função para o valor de retorno ...
Neil Barnwell
5
Comentário para usuários do Visual C ++: Digite $ ReturnValue na janela imediata ou na janela de inspeção. Pelo menos no meu VS 2010 funcionou!
sergiol 30/09
9
Para o VS2015, use $ ReturnValue1 .. caso você não queira ler as 20 respostas e os 100 comentários abaixo!
Felickz #
3
Qual é a resposta de 2019 para tudo isso? Essas respostas são super datadas.
dylanh724

Respostas:

264

Não que eu saiba. Note que se você fazer adicionar uma variável, ele será removido pelo compilador em compilações de qualquer maneira ...

Atualização: essa funcionalidade foi adicionada ao VS2013 . Você pode ver os valores de retorno nas janelas de automóveis ou usá-los na janela de inspeção $ReturnValue/ imediata.

O valor só pode ser visto diretamente após o retorno da função, portanto, a maneira mais fácil de acessá-lo é colocando um ponto de interrupção na chamada de função e passando (F10) a chamada.


Atualização para o VS2015: boo! infelizmente, não parece estar na atualização do VS2015 (devenv v14)
para o VS2017: está de volta. (devenv v15)

Marc Gravell
fonte
12
A razão para renunciar à temperatura é legibilidade e estilo, não eficiência, não?
orip 26/07/10
8
É possível desde o VS 2010 com o IntelliTrace: blogs.msdn.com/b/habibh/archive/2009/10/23/…
Daniel Hilgarth
2
O Intellitrace está disponível apenas no VS Ultimate Edition.
JMGH
3
@MarcGravell Sua resposta está errada ! Claro, demorei seis anos entre a sua resposta e a MS liberar esse recurso no VS13, mas ainda assim. Se você só tinha acrescentado " por enquanto ", como um aviso ... (Não, eu não sou retardado Ele. É uma piada, é claro que você divino, companheiro..)
Konrad Viltersten
6
@MarcGravell para VS2015: $ ReturnValue1 funciona! (testado na versão final)
GY
58

Isso pode ser feito no Visual Studio 2013 com CLR 4.5.1, de acordo com o site de comentários do cliente . Não estava disponível nas versões anteriores para C #.

(O Visual Studio 2008 e versões anteriores o suportavam no VB.NET. Ele sempre estava disponível para desenvolvedores de C / C ++.)

Alex Angas
fonte
11
Como você faz isso no Visual Studio 2010 C ++?
Utilizador
Microsoft Connect diz que há uma questão fundamental com código gerenciado que impede implementar isso de uma maneira confiável:
Dan Solovay
@DanSolovay As palavras que eles usam são "não conseguimos fazer a coisa certa de forma consistente" (para o VS11), mas "querem trazer isso de volta" e "estão procurando várias soluções possíveis para esse problema".
Alex Angas
A entrada de conexão está obsoleta. O recurso parece ser ... abandonada: (((
Softlion
11
É possível desde o VS 2010 com o IntelliTrace: blogs.msdn.com/b/habibh/archive/2009/10/23/…
Daniel Hilgarth
25

Concordo que isso é uma coisa muito útil: não apenas ver o valor de retorno do método antes de sair dele, mas também ver o valor de retorno dos métodos que acabei de passar. Eu o implementei como parte de uma extensão comercial para o Visual Studio chamada " OzCode ".

Com ele, você pode visualizar os valores de retorno do método diretamente no editor de código, como uma espécie de exibição do HUD:

Visualização de declaração

Para mais informações, consulte este vídeo .

Omer Raviv
fonte
23

Segundo a Microsoft, não há como implementá-lo de maneira confiável com código gerenciado. Este é um problema que eles conhecem e estão trabalhando:

Para aqueles que têm experiência em depurar códigos nativos C ++ ou VB6, você pode ter usado um recurso em que os valores de retorno de função são fornecidos na janela Autos. Infelizmente, essa funcionalidade não existe para o código gerenciado. Embora você possa solucionar esse problema atribuindo os valores de retorno a uma variável local, isso não é tão conveniente porque requer a modificação do seu código. No código gerenciado, é muito mais difícil determinar qual o valor de retorno de uma função que você passou por cima. Percebemos que não era possível fazer a coisa certa de forma consistente aqui e, portanto, removemos o recurso em vez de fornecer resultados incorretos no depurador. No entanto, queremos trazer isso de volta para você e nossas equipes de CLR e Depurador estão procurando várias soluções possíveis para esse problema. Infelizmente, isso não fará parte do 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
fonte
11
Por @Alex acima ( stackoverflow.com/a/3714884/402949 ), este está disponível para VS2013 com CLR 4.5
Dan Solovay
21

Em relação ao Visual Studio 2015:

De acordo com a resposta atualmente aceita por Marc Gravell:

Essa funcionalidade foi adicionada ao Visual Studio 2013 . Você pode ver os valores de retorno nas janelas de automóveis ou usar $ ReturnValue na janela de inspeção / imediata

Essa resposta também afirmou que essa funcionalidade não funciona no Visual Studio 2015. Isso não é (totalmente) verdade. Em Examinar valores de retorno de chamadas de método, há a seguinte nota:

Você deve ativar os avaliadores de expressão herdados para que $ ReturnValue seja reconhecido (Ferramentas / Opções / Depuração / Use os avaliadores de expressão herdados de C # e VB ). Caso contrário, você pode usar $ ReturnValue1 .

Eu testei isso no Visual Studio 2015 Enterprise:

  • Com os avaliadores de expressão herdados desativados: apenas $ ReturnValue1 funciona
  • Com legados avaliadores de expressão ligado: ambos $ ReturnValue e $ ReturnValue1 trabalho
PascalK
fonte
3
Isso não parece mais ser necessário. No VS 2015, atualização 3, tenho os avaliadores legados desativados e $ReturnValuefuncionam. No entanto, o valor de retorno não aparece em nenhum lugar se você tiver a Use managed compatibility modeopção de depuração ativada.
Nick
13

Se você for ao menu FerramentasOpções , IntelliTrace e alterar a configuração para coletar eventos e informações de chamada.

Você pode voltar ao evento de chamada anterior ( Ctrl+ Shift+ F11) e ver o valor temporário retornado da chamada de método na janela de automóveis como um filho do nome do método.

Isso não está mostrando o valor de retorno para o método em que você está. Apenas mostra o valor de retorno do último método chamado no método atual.

Então, tudo bem para

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

pois mostra o valor de retorno para someTableAdapter.getSomeData().

Mas não para:

int go(){return 100 * 99;}
Ross Buggins
fonte
12

Truque antigo dos dias anteriores ao .NET: Abra a janela Registros e veja o valor do registro EAX. Contém o valor de retorno da última função chamada.

ColinM
fonte
11
+1 para a velha escola mais próxima da abordagem do metal - no entanto, isso não funcionará para todos os valores de retorno (e cabe ao JIT'er, obviamente - quem sabe que otimização maluca pode decidir que não usará o EAX? ) Para tipos integrais, isso funcionará (principalmente?). Tipos de valores grandes são uma questão diferente (e, pelo que me lembro de alguma postagem no blog, eles também não serão exibidos no VS2013).
precisa saber é o seguinte
10

Saia do método go () usando Shift-F11 e, na janela de depuração "Autos", ele mostrará o valor de retorno da chamada do método que acabou de sair da pilha (nesse caso, o método go () que é o que você quer). Esse é o comportamento no Visual Studio 2005; Eu não usei o Visual Studio 2008, então não sei se isso se comporta da mesma maneira nessa versão.

LeopardSkinPillBoxHat
fonte
Eu tentei isso no VS2005 e no VS2008, mas realmente não o vejo. Eu tenho a janela "Autos" aberta, mas quando na função "go", a janela de automóveis está vazia. Além disso, ao sair da função (a chave de fechamento da função é amarela). Você pode me dar mais uma dica?
Dokman
Eu esperaria que a janela Autos estivesse vazia enquanto DENTRO da função go (). Você precisa sair COMPLETAMENTE da função (ou seja, o cursor de depuração deve estar apontando para a função que chamou CAL (go)) e, em seguida, você verá o valor de retorno para go () na janela Autos.
LeopardSkinPillBoxHat
@LeopardSkinPillBoxHat: não é possível fazer isso funcionar, mesmo com sua dica extra. Você está tentando isso no Visual Basic? Parece ter um melhor suporte para observar e alterar valores de retorno ...
Roman Starkov
@romkyns - O que aparece na janela "Automóveis" para você? Não mostra uma linha indicando o que a última função chamada retornou?
LeopardSkinPillBoxHat
2
@LeopardSkinPillBoxHat: não, não faz isso em c #. PS Uau, demorei um pouco para ver isso de novo.
Roman Starkov
7

Sim, existe uma maneira muito agradável. Uma desvantagem significativa é que você teria que esperar 5, talvez 6 anos. Desde que você postou em novembro de 2008, sugiro que você waaaaaa ...

... aaaait. E voilà! Somente para você, a MS lançou o Visual Studio 2013 mais recente, onde é um recurso padrão acessível a partir dos menus enquanto é executado no modo de depuração (menu DebugWindowsAutos ).

Konrad Viltersten
fonte
@ Doug Como a pergunta foi feita em novembro de 2008 e minha resposta veio em setembro de 2014. O pôster original provavelmente está satisfeito e não deseja mover o crédito. Mas concordo com você - não me importaria de mais alguns problemas com a minha resposta. Eu gosto de upsies e ganho de reputação. :)
Konrad Viltersten
Teve esse problema hoje. Obrigado por responder em 2014, mesmo que a edição inicial seja de 2008. Sua resposta é o que eu estava procurando.
AP
@AP Sem problemas. Parece um pouco com uma máquina do tempo para ver este post. Explosão do passado, hehe.
Konrad Viltersten
5

Existem muitas soluções alternativas, mas nenhuma parece satisfatória.

Para citar John Skeet abaixo (comente uma resposta excluída agora):

Ainda me parece inconveniente - especialmente se você não souber qual valor de retorno precisará antes de iniciar a depuração. Eu realmente não quero ter uma variável temporária bagunçando meu código toda vez que eu retornar algo.

Em teoria, o depurador pode ter uma returnvariável. Afinal: é apenas uma variável na pilha:

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

Portanto, considere isso uma solicitação de recurso para o Visual Studio.

doekman
fonte
há uma grande diferença entre uma variável (um local bem definido) e um valor na pilha. É um valor na pilha, mas não é uma variável (= local).
Marc Gravell
@ Marc: Não tenho certeza de como o CLR funciona, mas muitos compiladores colocam argumentos de função na pilha abaixo do ponteiro da pilha (sp) e variáveis ​​locais na pilha, acima do ponteiro da pilha. É exatamente isso que estou tentando mostrar. E OK, quando o valor de retorno é um tipo de referência, você obtém algum valor de ponteiro.
Dokman
11
Não está necessariamente na pilha. Na verdade, se você visualizar Debug -> Registros você está apto a vê-lo em EAX
Mark Sowul
5

Eu queria expandir a resposta do PascalK para que isso funcionasse no Visual Studio 2015, porque há um recurso oculto que não está documentado em Examinar valores de retorno de chamadas de método .

Se você aninhava chamadas de função, as pseudo-variáveis $ResultValueXsão criadas automaticamente, onde X se refere à ordem de chamada da função. Portanto, se você tiver uma chamada como Multiply(Five(), Six()), as seguintes pseudo-variáveis ​​serão criadas:

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

O Microsoft Visual C ++ costumava fazer isso, mas o Visual Studio não faz o AFAIK .. :(

Sprintstar
fonte
2

A única maneira que eu sei é colocar um ponto de interrupção na linha de retorno e, em seguida, chamar a janela do Quick Watch e inserir a expressão retornada:

someTableAdapter.getSomeData();

Mas isso só funciona se a chamada não alterar o estado de nenhum objeto (pois haverá uma segunda chamada para o mesmo método quando você retomará a execução).

Sylvain Rodrigue
fonte
5
Isso também funciona apenas se sua expressão não tiver lambdas.
Roman Starkov
1

Você também pode pedir para avaliar o valor na janela intermediária, se ele não definir sinalizadores ou outras variáveis, mas retornar apenas algo.

Biri
fonte
Você precisa incluir a lambda na questão, como eu usar a janela imediata também às vezes
Chris S
1

Eu acho que você pode determinar isso olhando para o registro RAX na janela Registers (Debug / Windows / Registers). Após sair (SHIFT + F11) da função, verifique o registro RAX. Eu não sei de fato, mas uma vez na lua você pode verificar um registro (dias antes do .NET) e ver o valor de retorno lá. Pode até ser uma combinação de RAX e RBX, etc.

Joe Rattz
fonte
1

Abrir a janela Debug → Autos aproxima-o. Ele não mostrará o valor de retorno real, mas mostrará o que foi avaliado na instrução de retorno.

GeekyMonkey
fonte
2
Não foi possível obter a janela de automóveis do VS2008 para mostrar algo assim. Você poderia por favor esclarecer?
Roman Starkov
return x + y; O que eu quis dizer foi que, se você definir um ponto de interrupção nessa linha, sua janela Debug-Autos exibirá os valores atuais de x e y. Como eu disse, só chega perto. Apenas Tentando Ser útil. Eu não acho que isso mereça um voto negativo.
GeekyMonkey
1

Sim, mudando para o VB.NET. ; P (Você acabou de dizer "Visual Studio".;)

Desde que me lembro (do Visual Basic a todas as versões do VB.NET), você pode simplesmente consultar o nome da função. Ele "funciona" como uma variável local declarada implicitamente no início da função e seu valor atual também é usado como valor de retorno sempre que a função sai por meio de instruções de não retorno ( Exit Functionou seja, apenas está caindo) e, é claro, quando a declaração de retorno é usada.

Também é definido para a expressão da instrução de retorno. Assim como uma variável local, seu valor pode ser inspecionado em qualquer ponto de execução dentro da função (inclusive após a declaração de retorno ser executada). C # não tem isso e deveria.

Esse pequeno recurso do VB.NET (mais a Exit Functioninstrução que ele habilita - outro recurso que o C # não tem e deve) é muito útil em uma forma de programação defensiva que eu pratico onde sempre inicializo o nome da função para o valor de falha / padrão como o primeira declaração. Então, em qualquer ponto de falha (que normalmente ocorre com muito mais frequência do que pontos de sucesso), posso simplesmente chamar a Exit Functiondeclaração (ou seja, sem ter que duplicar a expressão de falha / padrão ou mesmo um nome de constante / variável).

Tom
fonte
1

A resposta aceita não funciona corretamente com o Visual Studio 2015, mas, ao colocar um ponto de interrupção na última linha do método e pressionar F10, ele colocará todas as expressões do valor de retorno na janela locals.

Esben Skov Pedersen
fonte
Provavelmente, você também pode editar a resposta aceita para incluir seus comentários.
Dokman 27/07/16
0

Você pode tentar selecionar "someTableAdapter.getSomeData();", clicar com o botão direito do mouse e ir para o Quick Watch .

Yann Semet
fonte
-1

Arraste e solte a expressão de retorno em uma janela de inspeção.

Por exemplo, na declaração

return someTableAdapter.getSomeData();

arraste e solte

someTableAdapter.getSomeData()

em uma janela de inspeção e você verá o valor.

Você pode fazer isso para qualquer expressão.

Pita.O
fonte
2
O problema com isso: a expressão é avaliada duas vezes.
doekman
6
E as expressões de exibição não podem conter expressões lambda, que eu uso bastante.
21139 Steve Crane