Duplicata possible:
Le code dans une instruction Final se déclenchera-t-il si je renvoie une valeur dans un bloc Try?
Considérez le code suivant code C #. Le bloc "enfin" s'exécute-t-il?
public void DoesThisExecute() {
string ext = "xlsx";
string message = string.Empty;
try {
switch (ext) {
case "xls": message = "Great choice!"; break;
case "csv": message = "Better choice!"; break;
case "exe": message = "Do not try to break me!"; break;
default:
message = "You will not win!";
return;
}
}
catch (Exception) {
// Handle an exception.
}
finally {
MessageBox.Show(message);
}
}
Ha, après avoir fini d'écrire ceci, j'ai réalisé que j'aurais pu le tester moi-même dans Visual Studio. N'hésitez pas à répondre!
oui c'est le cas :-) http://msdn.Microsoft.com/en-us/library/zwc8s4fz.aspx
Non. Il s'exécutera toujours à condition que l'application soit toujours en cours d'exécution (sauf lors d'une exception FastFail , lien MSDN , comme d'autres l'ont noté). Il s'exécutera lorsqu'il quittera la partie try/catch du bloc.
Il ne s'exécutera PAS si l'application se bloque: se fait tuer par une commande de processus de suppression, etc. Ceci est très important, car si vous écrivez du code qui s'attend absolument à ce qu'il s'exécute, comme faire manuellement une restauration, et sinon, il le fera automatiquement commit, vous pouvez exécuter dans un scénario que l'application abandonne avant que cela ne se produise. Honnêtement, il s'agit d'un scénario extérieur, mais il est important d'en tenir compte dans ces situations.
À partir de la spécification MSDN C # de l'instruction try
:
Les instructions d'un bloc
finally
sont toujours exécutées lorsque le contrôle quitte une instructiontry
. Cela est vrai que le transfert de contrôle se produise à la suite d'une exécution normale, à la suite de l'exécution d'une instructionbreak
,continue
,goto
oureturn
, ou suite à la propagation d'une exception à partir de l'instructiontry
.
Il y a des cas où le bloc finally ne s'exécutera pas:
Il n'est pas totalement vrai que finally
sera toujours exécuté. Voir cette réponse de Haacked :
Deux possibilités:
StackOverflowException
ExecutingEngineException
Le bloc finally ne sera pas exécuté lorsqu'il y a une StackOverflowException car il n'y a pas de place sur la pile pour même exécuter plus de code. Elle ne sera pas non plus appelée lorsqu'il y a une ExecutingEngineException, ce qui est très rare.
En fait, pour toute sorte d'exception asynchrone (comme StackOverflowException
, OutOfMemoryException
, ThreadAbortException
), l'exécution d'un bloc finally
n'est pas garantie.
Cependant, ces exceptions sont des exceptions que vous ne pouvez généralement pas récupérer et, dans la plupart des cas, votre processus se termine de toute façon.
En fait, il y a aussi au moins un autre cas où finally
n'est pas exécuté comme décrit par Brian Rasmussen dans un maintenant question supprimée :
L'autre cas que je connais est si un finaliseur lève une exception. Dans ce cas, le processus prend également fin immédiatement et la garantie ne s'applique donc pas.
Le code ci-dessous illustre le problème
static void Main(string[] args) {
try {
DisposableType d = new DisposableType();
d.Dispose();
d = null;
GC.Collect();
GC.WaitForPendingFinalizers();
} catch {
Console.WriteLine("catch");
} finally {
Console.WriteLine("finally");
}
}
public class DisposableType : IDisposable {
public void Dispose() {
}
~DisposableType() {
throw new NotImplementedException();
}
}
Un essai fiable/catch/enfin devra utiliser régions d'exécution contraintes (CER) . Un exemple est fourni par MSDN:
[StructLayout(LayoutKind.Sequential)]
struct MyStruct
{
public IntPtr m_outputHandle;
}
sealed class MySafeHandle : SafeHandle
{
// Called by P/Invoke when returning SafeHandles
public MySafeHandle()
: base(IntPtr.Zero, true)
{
}
public MySafeHandle AllocateHandle()
{
// Allocate SafeHandle first to avoid failure later.
MySafeHandle sh = new MySafeHandle();
RuntimeHelpers.PrepareConstrainedRegions();
try { }
finally
{
MyStruct myStruct = new MyStruct();
NativeAllocateHandle(ref myStruct);
sh.SetHandle(myStruct.m_outputHandle);
}
return sh;
}
}
Une excellente source d'information est l'article suivant:
Depuis MSDN try-finally (référence C #)
Le bloc finally est utile pour nettoyer toutes les ressources allouées dans le bloc try ainsi que pour exécuter tout code qui doit s'exécuter même s'il existe une exception. Le contrôle est toujours passé au bloc finally quelle que soit la façon dont le bloc try se termine .
Oui, dans des circonstances normales (comme beaucoup d'autres l'ont souligné).
Le bloc finally est utile pour nettoyer toutes les ressources allouées dans le bloc try ainsi que pour exécuter tout code qui doit s'exécuter même s'il existe une exception. Le contrôle est toujours transmis au bloc finally, quelle que soit la façon dont le bloc try se termine.
Alors que catch est utilisé pour gérer les exceptions qui se produisent dans un bloc d'instructions, finalement est utilisé pour garantir l'exécution d'un bloc d'instructions de code, quelle que soit la façon dont le bloc try précédent est quitté.
Le bloc enfin s'exécutera, juste entre ces lignes:
message = "You will not win!";
return;
Oui, finally
s'exécute toujours, maintenant si le code du bloc finally provoquera une exception est une autre histoire.
La bonne réponse est oui.
Essayez de déboguer votre programme et de mettre un point d'arrêt et regardez comme le contrôle frappe toujours le bloc finalement.
Non, ce n'est pas le cas.
Il n'y a qu'une seule façon de contourner cela, c'est Environment.FailFast()
. Voir http://msdn.Microsoft.com/de-de/library/ms131100.aspx . Dans tous les autres cas, il est garanti que les finaliseurs seront exécutés ;-)
La méthode FailFast écrit la chaîne de message dans le journal des événements de l'application Windows, crée un vidage de votre application, puis termine le processus en cours. La chaîne de message est également incluse dans le rapport d'erreurs à Microsoft.
Utilisez la méthode FailFast au lieu de la méthode Exit pour terminer votre application si l'état de votre application est endommagé de manière irréparable, et l'exécution des blocs et finaliseurs try/finally de votre application corrompra les ressources du programme.
Réponse simple Oui. Mais il y a quelques "exceptions" à la règle.