Додаючи відповіді, які дають Марк Гравелл та Джон Скіт, важливо відзначити, що об'єкти та інші типи посилань поводяться аналогічно, коли повертаються, але мають деякі відмінності.
"Що", що повертається, відповідає тій же логіці, що і прості типи:
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");
}
}
}
Посилання, яке повертається, вже було оцінено до того, як локальній змінній буде призначено нове посилання в остаточному блоці.
Виконання по суті:
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;
}
}
Різниця полягає в тому, що все-таки можна було б змінити типи змінних за допомогою властивостей / методів об'єкта, що може спричинити несподіване поведінку, якщо ви не будете обережні.
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();
}
}
}
Друга річ, яку слід врахувати про спробу повернення, нарешті, це те, що параметри, передані "за посиланням", все ще можуть бути змінені після повернення. Оцінено лише повернене значення і зберігається у тимчасовій змінній, що чекає повернення, будь-які інші змінні все ще модифікуються звичайним чином. Контракт з параметром out може навіть не виконати, поки остаточно не перекриє цей шлях.
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;
}
}
}
Як і будь-яка інша конструкція потоку, "спробуйте повернутися, нарешті", має своє місце і може дозволити отримання більш чистого вигляду коду, ніж написання структури, яку він фактично компілює. Але його потрібно обережно використовувати, щоб уникнути гетчі.