Tidak - pada level IL Anda tidak dapat kembali dari dalam blok penanganan-terkecuali. Ini pada dasarnya menyimpannya dalam variabel dan kembali setelahnya
yaitu mirip dengan:
int tmp;
try {
tmp = ...
} finally {
...
}
return tmp;
misalnya (menggunakan reflektor):
static int Test() {
try {
return SomeNumber();
} finally {
Foo();
}
}
mengkompilasi ke:
.method private hidebysig static int32 Test() cil managed
{
.maxstack 1
.locals init (
[0] int32 CS$1$0000)
L_0000: call int32 Program::SomeNumber()
L_0005: stloc.0
L_0006: leave.s L_000e
L_0008: call void Program::Foo()
L_000d: endfinally
L_000e: ldloc.0
L_000f: ret
.try L_0000 to L_0008 finally handler L_0008 to L_000e
}
Ini pada dasarnya mendeklarasikan variabel lokal ( CS$1$0000
), menempatkan nilai ke dalam variabel (di dalam blok yang ditangani), kemudian setelah keluar dari blok memuat variabel, kemudian mengembalikannya. Reflektor menjadikan ini sebagai:
private static int Test()
{
int CS$1$0000;
try
{
CS$1$0000 = SomeNumber();
}
finally
{
Foo();
}
return CS$1$0000;
}
Pernyataan terakhir dijalankan, tetapi nilai kembali tidak terpengaruh. Urutan eksekusi adalah:
Berikut ini adalah program singkat untuk diperagakan:
Ini mencetak "coba" (karena itulah yang dikembalikan) dan kemudian "akhirnya" karena itulah nilai baru x.
Tentu saja, jika kita mengembalikan referensi ke objek yang dapat diubah (mis. StringBuilder) maka setiap perubahan yang dilakukan pada objek di blok akhirnya akan terlihat saat kembali - ini tidak memengaruhi nilai pengembalian itu sendiri (yang hanya merupakan referensi).
sumber
return
pernyataan, dan nilai itu akan dikembalikan. Ekspresi tidak dievaluasi ketika kontrol meninggalkan metode.Klausa akhirnya dieksekusi setelah pernyataan kembali tetapi sebelum benar-benar kembali dari fungsi. Ini tidak ada hubungannya dengan keselamatan benang, saya pikir. Ini bukan hack - yang akhirnya dijamin akan selalu berjalan tidak peduli apa yang Anda lakukan di blok percobaan atau blok tangkapan Anda.
sumber
Menambah jawaban yang diberikan oleh Marc Gravell dan Jon Skeet, penting untuk mencatat objek dan tipe referensi lainnya berperilaku sama ketika dikembalikan tetapi memiliki beberapa perbedaan.
"Apa" yang dikembalikan mengikuti logika yang sama dengan tipe sederhana:
Referensi yang dikembalikan sudah dievaluasi sebelum variabel lokal diberi referensi baru di blok akhirnya.
Eksekusi pada dasarnya:
Perbedaannya adalah masih mungkin untuk memodifikasi tipe yang bisa berubah menggunakan properti / metode objek yang dapat mengakibatkan perilaku tak terduga jika Anda tidak hati-hati.
Hal kedua yang perlu dipertimbangkan tentang try-return-akhirnya adalah bahwa parameter yang lulus "dengan referensi" masih dapat dimodifikasi setelah pengembalian. Hanya nilai kembali yang telah dievaluasi dan disimpan dalam variabel sementara yang menunggu untuk dikembalikan, variabel lainnya masih dimodifikasi dengan cara normal. Kontrak parameter keluar bahkan bisa tidak terpenuhi sampai akhirnya memblokir dengan cara ini.
Seperti aliran lain membangun "coba-kembali-akhirnya" memiliki tempatnya dan dapat memungkinkan untuk mencari kode yang lebih bersih daripada menulis struktur yang sebenarnya dikompilasi. Tetapi harus digunakan dengan hati-hati untuk menghindari gotcha.
sumber
Jika
x
merupakan variabel lokal, saya tidak melihat intinya, karenax
akan secara efektif diatur ke nol pula ketika metode ini keluar dan nilai nilai kembali tidak nol (karena ditempatkan dalam register sebelum panggilan untuk mengaturx
ke nol).Saya hanya dapat melihat hal ini terjadi jika Anda ingin menjamin perubahan nilai bidang setelah pengembalian (dan setelah nilai kembali ditentukan).
sumber