Bisakah saya mengetahui nilai kembali sebelum kembali saat debugging di Visual Studio?

387

Ambil fungsi berikut:

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

Ketika saya menetapkan breakpoint dalam fungsi ini, apakah ada kemungkinan untuk memeriksa nilai yang dikembalikan? go()secara langsung digabungkan ke datagrid di .aspxhalaman.

Satu-satunya cara untuk memeriksa datatable yang dikembalikan adalah dengan menggunakan variabel sementara. Namun, itu agak merepotkan. Apakah tidak ada cara lain?

doekman
sumber
1
Anda dapat menambahkan arloji jika Anda naik kembali ke tumpukan panggilan
Chris S
Anda dulu dapat melakukan ini di VB6, saya ingat. Tetapi saat itu sintaks untuk fungsi yang terlibat mengatur nilai fungsi ke nilai kembali ...
Neil Barnwell
5
Komentar untuk pengguna Visual C ++: Ketik $ ReturnValue di Jendela Segera atau Jendela Tonton. Setidaknya pada VS 2010 saya berhasil!
sergiol
9
Untuk VS2015 gunakan $ ReturnValue1 .. jika Anda tidak ingin membaca 20 jawaban dan 100 komentar di bawah ini!
felickz
3
Apa jawaban 2019 untuk semua ini? Jawaban-jawaban ini super tanggal.
dylanh724

Jawaban:

264

Tidak yang saya tahu. Catatan bahwa jika Anda melakukan menambahkan variabel, itu akan bisa dihapus oleh compiler dalam rilis membangun pula ...

Pembaruan: Fungsi ini telah ditambahkan ke VS2013 . Anda dapat melihat nilai kembali di jendela autos atau digunakan $ReturnValuedi jendela arloji / langsung.

Nilai hanya dapat dilihat secara langsung setelah kembali dari fungsi, sehingga cara termudah untuk mengaksesnya adalah dengan meletakkan breakpoint pada pemanggilan fungsi dan melangkahi (F10) panggilan.


Pembaruan untuk VS2015: boo! sayangnya, sepertinya tidak ada di VS2015 (devenv v14)
Pembaruan untuk VS2017: itu kembali. (devenv v15)

Marc Gravell
sumber
12
Alasan untuk melupakan temp adalah keterbacaan & gaya, bukan efisiensi, bukan?
orip
8
Hal ini dimungkinkan sejak VS 2010 dengan IntelliTrace: blogs.msdn.com/b/habibh/archive/2009/10/23/…
Daniel Hilgarth
2
Intellitrace hanya tersedia dalam VS Ultimate Edition.
JMGH
3
@MarcGravell Jawaban Anda salah ! Tentu, saya butuh enam tahun antara balasan Anda dan MS merilis fitur itu di VS13, tetapi masih. Jika Anda hanya menambahkan " untuk sementara waktu " sebagai penafian ... (Tidak, saya tidak terbelakang. Tentu saja ini lelucon. Anda seperti dewa, sobat.)
Konrad Viltersten
6
@MarcGravell untuk VS2015: $ ReturnValue1 berfungsi! (diuji dalam versi akhir)
GY
58

Ini dapat dilakukan di Visual Studio 2013 dengan CLR 4.5.1 sesuai dengan situs umpan balik pelanggan . Itu tidak tersedia di versi sebelumnya untuk C #.

(Visual Studio 2008 dan sebelumnya mendukungnya untuk VB.NET. Selalu tersedia untuk pengembang C / C ++.)

Alex Angas
sumber
1
Bagaimana Anda melakukan ini di Visual Studio 2010 C ++?
Pengguna
Microsoft Connect mengatakan ada masalah mendasar dengan kode terkelola yang mencegah penerapan ini dengan cara yang dapat diandalkan:
Dan Solovay
@DanSolovay Kata-kata yang mereka gunakan adalah "kami tidak bisa melakukan hal yang benar secara konsisten" (untuk VS11) tetapi mereka "ingin membawa ini kembali" dan "mencari sejumlah solusi potensial untuk masalah ini".
Alex Angas
Entri koneksi basi. Fitur ini sepertinya ... ditinggalkan: (((
Softlion
1
Hal ini dimungkinkan sejak VS 2010 dengan IntelliTrace: blogs.msdn.com/b/habibh/archive/2009/10/23/…
Daniel Hilgarth
25

Saya setuju bahwa ini adalah hal yang sangat berguna untuk dimiliki: tidak hanya melihat nilai balik metode sebelum melangkah keluar, tetapi juga melihat nilai balik metode yang baru saja saya melangkahi. Saya menerapkannya sebagai bagian dari ekstensi komersial ke Visual Studio yang disebut " OzCode ".

Dengan itu, Anda dapat melihat nilai metode pengembalian langsung pada editor kode, sebagai semacam tampilan HUD:

Pernyataan Visualisasi

Untuk informasi lebih lanjut, silakan lihat video ini .

Omer Raviv
sumber
23

Menurut Microsoft, tidak ada cara untuk mengimplementasikan ini secara andal dengan kode yang dikelola. Ini adalah masalah yang mereka sadari dan sedang mereka kerjakan:

Bagi mereka di luar sana yang memiliki pengalaman debugging kode C ++ atau VB6 asli, Anda mungkin telah menggunakan fitur di mana nilai-nilai fungsi kembali disediakan untuk Anda di jendela Autos. Sayangnya, fungsi ini tidak ada untuk kode yang dikelola. Meskipun Anda dapat mengatasi masalah ini dengan menetapkan nilai kembali ke variabel lokal, ini tidak nyaman karena memerlukan modifikasi kode Anda. Dalam kode terkelola, jauh lebih sulit untuk menentukan berapa nilai pengembalian fungsi yang Anda lewati. Kami menyadari bahwa kami tidak dapat melakukan hal yang benar secara konsisten di sini sehingga kami menghapus fitur tersebut daripada memberikan Anda hasil yang salah dalam debugger. Namun, kami ingin mengembalikan ini untuk Anda dan tim CLR dan Debugger kami sedang mencari sejumlah solusi potensial untuk masalah ini. Sayangnya ini tidak akan menjadi bagian dari 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
sumber
1
Per @Alex di atas ( stackoverflow.com/a/3714884/402949 ), ini tersedia untuk VS2013 dengan CLR 4.5
Dan Solovay
21

Mengenai Visual Studio 2015:

Menurut jawaban yang saat ini diterima oleh Marc Gravell:

Ini fungsi telah ditambahkan ke Visual Studio 2013 . Anda dapat melihat nilai kembali di jendela autos atau menggunakan $ ReturnValue di jendela arloji / langsung

Jawaban itu juga menyatakan bahwa fungsi ini tidak berfungsi di Visual Studio 2015. Ini tidak (sepenuhnya) benar. Pada Periksa nilai pengembalian panggilan metode ada catatan berikut:

Anda harus mengaktifkan pengevaluasi ekspresi lama agar $ ReturnValue dapat dikenali (Alat / Opsi / Debugging / Gunakan pengevaluasi ekspresi C # dan VB lama ). Jika tidak, Anda dapat menggunakan $ ReturnValue1 .

Saya menguji ini di Visual Studio 2015 Enterprise:

  • Dengan evaluator ekspresi lama dimatikan: hanya $ ReturnValue1 yang berfungsi
  • Dengan warisan ekspresi evaluator diaktifkan: baik $ ReturnValue dan $ ReturnValue1 kerja
PascalK
sumber
3
Tampaknya ini tidak lagi diperlukan. Pada Pembaruan 3 VS 2015, saya memiliki penilai lama dinonaktifkan dan $ReturnValueberfungsi. Namun, nilai kembali tidak muncul di mana pun jika Anda Use managed compatibility modemengaktifkan opsi debugging.
Nick
13

Jika Anda masuk ke menu AlatOpsi , IntelliTrace, dan ubah pengaturan untuk mengumpulkan acara dan memanggil informasi.

Anda dapat kembali ke acara panggilan sebelumnya ( Ctrl+ Shift+ F11) dan melihat nilai sementara yang dikembalikan dari panggilan metode di jendela autos sebagai anak dari nama metode.

Ini tidak menunjukkan kepada Anda nilai pengembalian untuk metode yang Anda gunakan. Itu hanya menunjukkan nilai pengembalian metode terakhir yang disebut dalam metode saat ini.

Jadi, tidak masalah untuk itu

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

karena ini menunjukkan nilai pengembalian untuk someTableAdapter.getSomeData().

Tetapi tidak untuk:

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

Trik lama dari hari-hari pra .NET: Buka jendela Register dan lihat nilai register EAX. Ini berisi nilai pengembalian fungsi terakhir yang disebut.

Kolin
sumber
1
+1 untuk sekolah tua yang lebih dekat dengan pendekatan logam - ini, bagaimanapun, tidak akan bekerja untuk semua nilai pengembalian (dan terserah pada JIT'er, jelas - siapa yang tahu optimasi gila apa yang mungkin diputuskan yang tidak akan menggunakan EAX? ). Untuk tipe integral akan bekerja (kebanyakan?). Jenis nilai besar adalah masalah yang berbeda (dan sejauh yang saya ingat dari beberapa posting blog, itu juga tidak akan ditampilkan di VS2013).
JimmiTh
10

Langkah keluar dari metode go () menggunakan Shift-F11, dan kemudian di jendela debug "Autos" itu akan menunjukkan nilai kembali dari panggilan metode yang baru saja muncul dari stack (dalam hal ini, metode go () yang merupakan apa maumu). Ini adalah perilaku dalam Visual Studio 2005; Saya belum pernah menggunakan Visual Studio 2008 jadi saya tidak tahu apakah ini berperilaku yang sama dalam versi itu.

LeopardSkinPillBoxHat
sumber
Saya sudah mencoba ini di VS2005 dan VS2008, tapi saya tidak benar-benar melihatnya. Saya memiliki jendela "Autos" terbuka, tetapi ketika dalam fungsi "go", jendela autos kosong. Juga ketika melangkah keluar dari fungsi (kurung kurawal penutupan fungsi berwarna kuning). Bisakah Anda memberi saya satu petunjuk lagi?
doekman
Saya berharap Autos-window menjadi kosong sementara DI DALAM fungsi go (). Anda harus keluar sama sekali dari fungsi (mis. Kursor debug harus menunjuk ke fungsi yang telah CALLED go ()) dan kemudian Anda akan melihat nilai balik untuk go () di jendela Autos.
LeopardSkinPillBoxHat
@LeopardSkinPillBoxHat: tidak bisa menjalankan ini, bahkan dengan petunjuk tambahan Anda. Apakah Anda mencoba ini dalam Visual Basic? Tampaknya memiliki dukungan yang lebih baik untuk mengamati dan mengubah nilai kembali ...
Roman Starkov
@romkyns - Apa yang muncul di jendela "Autos" untuk Anda? Bukankah itu menunjukkan garis yang menunjukkan apa fungsi yang terakhir dipanggil kembali?
LeopardSkinPillBoxHat
2
@LeopardSkinPillBoxHat: tidak, tidak bisa melakukannya di C #. PS Wow, butuh waktu beberapa saat untuk melihatnya lagi.
Roman Starkov
7

Ya, ada cara yang sangat bagus. Satu kekurangan signifikan adalah Anda harus menunggu selama 5, mungkin 6 tahun. Karena saya melihat bahwa Anda memposting pada November 2008, saya sarankan Anda waaaaaa ...

... aaaait. Dan voila! Hanya untuk Anda, MS telah merilis Visual Studio 2013 terbaru yang merupakan fitur default yang dapat diakses dari menu saat berjalan dalam mode debug (menu DebugWindowsAutos ).

Konrad Viltersten
sumber
@Doug Karena pertanyaan itu diajukan November 2008 dan balasan saya datang September 2014. Poster asli mungkin puas dan tidak ingin memindahkan kredit. Tapi saya setuju dengan Anda - saya tidak akan keberatan beberapa upsies atas jawaban saya. Saya suka upsies dan rep keuntungan. :)
Konrad Viltersten
Punya masalah ini hari ini. Terima kasih telah membalas pada 2014 meskipun masalah awalnya adalah tahun 2008. Jawaban Anda adalah apa yang saya cari.
AP
@ AAP Tidak ada masalah. Rasanya agak seperti mesin waktu untuk melihat posting ini. Ledakan dari masa lalu, hehe.
Konrad Viltersten
5

Ada banyak solusi, tetapi tidak ada yang memuaskan.

Mengutip John Skeet di bawah ini (mengomentari jawaban yang sekarang dihapus):

Masih terlihat tidak nyaman bagi saya - terutama jika Anda tidak tahu nilai pengembalian yang Anda perlukan sebelum memulai debugging. Saya benar-benar tidak ingin harus memiliki variabel sementara yang mengacaukan kode saya setiap kali saya mengembalikan apa pun.t

Secara teori, debugger bisa memiliki return-variable. Setelah semua: itu hanya variabel di stack:

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

Jadi pertimbangkan ini permintaan fitur untuk Visual Studio.

doekman
sumber
ada perbedaan yang cukup besar antara variabel (lokal yang terdefinisi dengan baik) dan nilai pada stack. Ini adalah nilai pada stack, tetapi ini bukan variabel (= lokal).
Marc Gravell
@ Markc: Saya tidak yakin bagaimana CLR bekerja, tetapi banyak kompiler menaruh argumen fungsi pada stack di bawah stack pointer (sp), dan variabel lokal pada stack, di atas stack pointer. Itulah yang ingin saya tunjukkan. Dan OK, ketika nilai kembali adalah tipe referensi, Anda hanya mendapatkan beberapa nilai pointer.
doekman
1
Itu tidak harus di tumpukan. Bahkan, jika Anda melihat Debug -> Register, Anda cenderung melihatnya di EAX
Mark Sowul
5

Saya ingin memperluas jawaban PascalK untuk mendapatkan ini berfungsi di Visual Studio 2015, karena ada fitur tersembunyi yang tidak didokumentasikan dalam Memeriksa nilai pengembalian panggilan metode .

Jika Anda memiliki panggilan fungsi bersarang, variabel pseudo $ResultValueXsecara otomatis dibuat, di mana X mengacu pada urutan panggilan fungsi. Jadi jika Anda memiliki panggilan seperti Multiply(Five(), Six()), pseudo-variable berikut dibuat:

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

Microsoft Visual C ++ digunakan untuk melakukan ini, tetapi Visual Studio tidak AFAIK .. :(

Sprintstar
sumber
2

Satu-satunya cara yang saya tahu adalah menempatkan breakpoint pada baris kembali dan kemudian memanggil jendela Quick Watch dan memasukkan ekspresi yang dikembalikan:

someTableAdapter.getSomeData();

Tapi ini hanya berfungsi jika panggilan tidak mengubah status objek apa pun (karena akan ada panggilan kedua ke metode yang sama ketika Anda akan melanjutkan eksekusi).

Sylvain Rodrigue
sumber
5
Ini juga hanya berfungsi jika ekspresi Anda tidak memiliki lambda.
Roman Starkov
1

Anda juga dapat meminta untuk mengevaluasi nilai di jendela perantara juga, jika tidak menetapkan flag atau variabel lain, tetapi hanya mengembalikan sesuatu.

Biri
sumber
Anda perlu memasukkan lambda dalam pertanyaan, karena saya kadang
Chris S
1

Saya pikir Anda dapat menentukan ini dengan melihat register RAX di jendela Register (Debug / Windows / Registers). Setelah melangkah keluar (SHIFT + F11) dari fungsi, periksa register RAX. Saya tidak tahu pasti, tetapi sekali di bulan Anda dapat memeriksa register (pra. NET hari) dan melihat nilai kembali di sana. Bahkan mungkin kombinasi RAX dan RBX, dll.

Joe Rattz
sumber
1

Membuka Debug → Autos membuat Anda dekat. Itu tidak akan menunjukkan nilai pengembalian yang sebenarnya, tetapi itu akan menunjukkan apa yang dievaluasi dalam pernyataan pengembalian.

GeekyMonkey
sumber
2
Tidak bisa mendapatkan jendela mobil VS2008 untuk menunjukkan hal seperti itu. Bisakah Anda menjelaskan?
Roman Starkov
return x + y; Yang saya maksudkan adalah jika Anda menetapkan breakpoint pada baris ini, maka jendela Debug-Autos Anda akan menampilkan nilai saat ini untuk x dan y. Seperti yang saya katakan, itu hanya membuat Anda dekat. Hanya mencoba untuk menjadi berguna. Saya tidak berpikir itu layak untuk downvote.
GeekyMonkey
1

Ya, dengan beralih ke VB.NET. ; P (Anda baru saja mengatakan "Visual Studio".;)

Selama saya dapat mengingat (dari Visual Basic melalui semua versi VB.NET), Anda dapat dengan mudah menanyakan nama fungsi. Ini "berfungsi" seperti variabel lokal yang secara implisit dinyatakan pada awal fungsi dan nilai saat ini juga digunakan sebagai nilai kembali setiap kali fungsi keluar melalui pernyataan non-kembali berarti (yaitu Exit Functionatau hanya jatuh melalui) dan tentu saja, ketika pernyataan pengembalian digunakan.

Ini juga diatur ke ekspresi pernyataan kembali. Sama seperti variabel lokal, nilainya dapat diperiksa pada setiap titik eksekusi di dalam fungsi (termasuk setelah pernyataan pengembalian dieksekusi). C # tidak memiliki ini dan seharusnya.

Fitur VB.NET kecil itu (ditambah Exit Functionpernyataan yang memungkinkannya - fitur C # lainnya tidak dimiliki dan seharusnya) sangat berguna dalam bentuk pemrograman defensif yang saya praktikkan di mana saya selalu menginisialisasi nama fungsi ke nilai kegagalan / standar sebagai pernyataan pertama. Kemudian, pada setiap titik kegagalan (yang biasanya terjadi jauh lebih sering daripada titik keberhasilan), saya cukup memanggil Exit Functionpernyataan (yaitu tanpa harus menduplikasi kegagalan / ekspresi default atau bahkan nama konstanta / variabel).

Tom
sumber
1

Jawaban yang diterima tidak bekerja dengan baik dengan Visual Studio 2015, tetapi dengan menempatkan break point pada baris terakhir dari metode dan menekan F10, itu akan menempatkan semua ekspresi dari nilai pengembalian ke jendela lokal.

Esben Skov Pedersen
sumber
Anda mungkin juga dapat mengedit jawaban yang diterima untuk memasukkan komentar Anda.
doekman
0

Anda dapat mencoba memilih "someTableAdapter.getSomeData();", klik kanan padanya, dan pilih Quick Watch .

Yann Semet
sumber
-1

Seret dan lepas ekspresi kembali ke jendela arloji.

Misalnya dalam pernyataannya

return someTableAdapter.getSomeData();

seret dan lepas

someTableAdapter.getSomeData()

ke jendela arloji, dan Anda akan melihat nilainya.

Anda dapat melakukan ini untuk ekspresi apa pun.

Pita.O
sumber
2
Masalah dengan itu: ekspresi dievaluasi dua kali.
doekman
6
Dan menonton ekspresi tidak bisa mengandung ekspresi lambda, yang saya gunakan sedikit adil.
Steve Crane