En plus des réponses données par Marc Gravell et Jon Skeet, il est important de noter que les objets et autres types de référence se comportent de la même manière lorsqu'ils sont retournés, mais présentent quelques différences.
Le "Quoi" qui est retourné suit la même logique que les types simples:
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");
}
}
}
La référence renvoyée a déjà été évaluée avant que la variable locale se voit attribuer une nouvelle référence dans le bloc finally.
L'exécution est essentiellement:
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;
}
}
La différence est qu'il serait toujours possible de modifier les types mutables en utilisant les propriétés / méthodes de l'objet, ce qui peut entraîner des comportements inattendus si vous ne faites pas attention.
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();
}
}
}
Une deuxième chose à considérer à propos de try-return-enfin est que les paramètres passés "par référence" peuvent toujours être modifiés après le retour. Seule la valeur de retour a été évaluée et est stockée dans une variable temporaire en attente de retour, toutes les autres variables sont toujours modifiées de la manière normale. Le contrat d'un paramètre de sortie peut même rester inachevé jusqu'à ce qu'il soit finalement bloqué de cette façon.
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;
}
}
}
Comme toute autre construction de flux, «try-return-finally» a sa place et peut permettre un code plus propre que d'écrire la structure dans laquelle il se compile. Mais il doit être utilisé avec précaution pour éviter les pièges.