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:
class Test {
public static Exception AnException() {
Exception ex = new Exception("Me");
try {
return ex;
} finally {
// Reference unchanged, Local variable changed
ex = new Exception("Not Me");
}
}
}
Referensi yang dikembalikan sudah dievaluasi sebelum variabel lokal diberi referensi baru di blok akhirnya.
Eksekusi pada dasarnya:
class Test {
public static Exception AnException() {
Exception ex = new Exception("Me");
Exception CS$1$0000 = null;
try {
CS$1$0000 = ex;
} finally {
// Reference unchanged, Local variable changed
ex = new Exception("Not Me");
}
return CS$1$0000;
}
}
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.
class Test2 {
public static System.IO.MemoryStream BadStream(byte[] buffer) {
System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer);
try {
return ms;
} finally {
// Reference unchanged, Referenced Object changed
ms.Dispose();
}
}
}
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.
class ByRefTests {
public static int One(out int i) {
try {
i = 1;
return i;
} finally {
// Return value unchanged, Store new value referenced variable
i = 1000;
}
}
public static int Two(ref int i) {
try {
i = 2;
return i;
} finally {
// Return value unchanged, Store new value referenced variable
i = 2000;
}
}
public static int Three(out int i) {
try {
return 3;
} finally {
// This is not a compile error!
// Return value unchanged, Store new value referenced variable
i = 3000;
}
}
}
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.