Thêm vào các câu trả lời được đưa ra bởi Marc Gravell và Jon Skeet, điều quan trọng cần lưu ý là các đối tượng và các loại tham chiếu khác hoạt động tương tự khi trả về nhưng có một số khác biệt.
"Cái gì" được trả về tuân theo logic giống như các loại đơn giản:
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");
}
}
}
Tham chiếu đang được trả về đã được đánh giá trước khi biến cục bộ được gán một tham chiếu mới trong khối cuối cùng.
Việc thực hiện về cơ bản là:
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;
}
}
Sự khác biệt là vẫn có thể sửa đổi các loại có thể thay đổi bằng cách sử dụng các thuộc tính / phương thức của đối tượng có thể dẫn đến các hành vi không mong muốn nếu bạn không cẩn thận.
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();
}
}
}
Điều thứ hai cần xem xét về việc thử trả lại-cuối cùng là các tham số được truyền "bằng tham chiếu" vẫn có thể được sửa đổi sau khi trả về. Chỉ có giá trị trả về đã được ước tính và được lưu trữ trong một biến tạm thời đang chờ được trả về, bất kỳ biến nào khác vẫn được sửa đổi theo cách thông thường. Hợp đồng của một tham số out thậm chí có thể không được thực hiện cho đến khi cuối cùng chặn theo cách này.
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;
}
}
}
Giống như bất kỳ dòng chảy nào khác, "try-return-cuối cùng" có vị trí của nó và có thể cho phép tìm mã sạch hơn là viết cấu trúc mà nó thực sự biên dịch. Nhưng nó phải được sử dụng cẩn thận để tránh gotcha.