Dodając do odpowiedzi udzielonych przez Marca Gravella i Jona Skeeta, ważne jest, aby pamiętać, że obiekty i inne typy referencji zachowują się podobnie po powrocie, ale mają pewne różnice.
Zwracane „Co” podlega tej samej logice co typy proste:
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");
}
}
}
Zwracane odwołanie zostało już ocenione, zanim zmienna lokalna otrzyma nowe odwołanie w bloku na końcu.
Wykonanie jest zasadniczo:
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;
}
}
Różnica polega na tym, że nadal można modyfikować zmienne typy przy użyciu właściwości / metod obiektu, co może spowodować nieoczekiwane zachowania, jeśli nie będziesz ostrożny.
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();
}
}
}
Drugą rzeczą do rozważenia w przypadku try-return-wreszcie jest to, że parametry przekazane „przez referencję” mogą być nadal modyfikowane po powrocie. Tylko zwracana wartość została oszacowana i jest przechowywana w zmiennej tymczasowej oczekującej na zwrot , pozostałe zmienne są nadal modyfikowane w normalny sposób. Kontrakt parametru wyjściowego może nawet nie zostać wypełniony, dopóki ostatecznie nie zablokuje w ten sposób.
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;
}
}
}
Jak każda inna konstrukcja przepływu, „try-return-Wreszcie” ma swoje miejsce i może pozwolić na czystszy wygląd kodu niż pisanie struktury, do której faktycznie się kompiluje. Ale należy go używać ostrożnie, aby uniknąć gotcha.