web-dev-qa-db-fra.com

Utiliser un bloc «essayer enfin» sans bloc «attraper»

Y a-t-il des situations où il convient d'utiliser un try-finally bloc sans bloc catch?

65
mkus

Vous l'utiliseriez pour vous assurer que certaines actions se produisent après le contenu try ou sur une exception, mais lorsque vous ne souhaitez pas consommer cette exception.

Pour être clair, cela ne cache pas les exceptions. Le bloc finally est exécuté avant que l'exception ne se propage dans la pile des appels.

Vous l'utiliseriez également par inadvertance lorsque vous utilisez le mot clé using, car il se compile en try-finally (pas une conversion exacte, mais pour les besoins de l'argument, elle est assez proche).

try
{
    TrySomeCodeThatMightException();
}
finally
{
    CleanupEvenOnFailure();
}

Le code exécuté dans finally n'est pas garanti de fonctionner, cependant le cas où il n'est pas garanti est assez Edge - je ne m'en souviens même pas. Tout ce dont je me souviens, c'est que si vous êtes dans ce cas, il y a de fortes chances que ne pas exécuter le finally ne soit pas votre plus gros problème :-) alors ne le transpirez pas.

Mise à jour depuis Tobias: finally ne fonctionnera pas si le processus est tué.

Mise à jour de Paddy: Conditions quand finalement ne s'exécute pas dans un bloc .net try..finally

L'exemple le plus courant que vous pouvez voir est la suppression d'une connexion à une base de données ou d'une ressource externe même si le code échoue:

using (var conn = new SqlConnection("")) // Ignore the fact we likely use ORM ;-)
{
    // Do stuff.
}

Compile en quelque chose comme:

SqlConnection conn;

try
{
    conn = new SqlConnection("");
    // Do stuff.
}
finally
{
    if (conn != null)
        conn.Dispose();
}
101
Adam Houldsworth

using est équivalent try-finally. Vous n'utiliserez que try-finally lorsque vous voulez faire un peu de nettoyage à l'intérieur finally et ne vous souciez pas de l'exception.

meilleure approche sera

try
{
   using(resource)
   {
       //Do something here
   }   
}catch(Exception)
{
     //Handle Error
}

Faire même si le nettoyage appelé par using échoue, votre code n'échouera pas.

Il existe certaines conditions lorsque finally ne sera pas exécuté.

  • S'il y a StackOverflowException ou ExecutingEngineException.
  • Le processus est tué à partir d'une source externe.

J'espère que cela répond à votre doute.

5
Amar Palsapure

Si vous disposez, par exemple, d'une ressource non gérée que vous créez et utilisez dans le bloc try, vous pouvez utiliser le bloc finally pour vous assurer de libérer cette ressource. Le bloc finally sera toujours exécuté malgré ce qui se passe (par exemple des exceptions) dans le bloc try.

Par exemple. l'instruction lock (x) est vraiment:

System.Threading.Monitor.Enter(x); 
try { ... } 
finally 
{ 
    System.Threading.Monitor.Exit(x); 
} 

Le bloc enfin sera toujours appelé pour s'assurer que le verrou exclusif est libéré.

3
Jeb

Bonne explication en utilisant le code:

void MyMethod1()
{
    try
    {
        MyMethod2();
        MyMethod3();
    }
    catch(Exception e)
    {
        //do something with the exception
    }
}


void MyMethod2()
{
    try
    {
        //perform actions that need cleaning up
    }
    finally
    {
        //clean up
    }
}


void MyMethod3()
{
    //do something
}

Si MyMethod2 ou MyMethod3 lève une exception, elle sera interceptée par MyMethod1. Cependant, le code dans MyMethod2 doit exécuter du code de nettoyage, par exemple fermeture d'une connexion à une base de données, avant que l'exception ne soit transmise à MyMethod1.

http://forums.asp.net/t/1092267.aspx?Try+without+Catch+but+with+finally+doesn+t+throw+error+Why+no+syntax+error+

2
donstack

Voici une situation où vous voudrez peut-être utiliser try finalement: lorsque vous utiliseriez normalement une instruction using, mais ne le pouvez pas parce que vous appelez une méthode par réflexion.

Cela ne fonctionnera pas

using (objMsg  =  Activator.CreateInstance(TypeAssist.GetTypeFromTypeName("omApp.MessagingBO")))
{

}

utilisez plutôt

           object objMsg = null;
            try
            {
                objMsg
                   = Activator.CreateInstance(TypeAssist.GetTypeFromTypeName("myAssembly.objBO"));

                strResponse = (string)objMsg.GetType().InvokeMember("MyMethod", BindingFlags.Public
                        | BindingFlags.Instance | BindingFlags.InvokeMethod, null, objMsg,
                        new object[] { vxmlRequest.OuterXml });
            }               
            finally
            {
                if (objMsg!=null)
                    ((IDisposable)objMsg).Dispose();
            }
1
jazza1000

Vous avez besoin d'un bloc finally, quand peu importe quelles exceptions (le cas échéant) sont interceptées ou même si aucune n'est interceptée, vous voulez toujours exécuter du code avant la fin du bloc. Par exemple, vous souhaiterez peut-être fermer un fichier ouvert.

Voir aussi try-finally

1
IanNorton

essayez/enfin: lorsque vous ne voulez pas gérer d'exceptions mais que vous voulez vous assurer que certaines actions se produisent, qu'une exception soit levée ou non par le code appelé.

1
Mitch Wheat

Jetez un œil sur le lien suivant: https://softwareengineering.stackexchange.com/questions/131397/why-use-try-finally-without-a-catch-clause

Cela dépend de l'architecture de votre application et de l'opération que vous effectuez dans le bloc.

0
Harsh

Voici un cas d'utilisation que j'utilise toujours (euh ..):

int? x; //note the nullable type here!
try
{
    x = int.Parse(someString);
}
catch { } //don't care, let it just be null
0
Alex

Je ne sais rien de C #, mais il semble que tout ce que vous pourriez faire avec un essai, enfin, vous pourriez le faire plus élégamment avec un en utilisant l'instruction . C++ n'a même pas de finalement comme n résultat de son RAII .

0
Neil G

1. nous pouvons utiliser le bloc try sans catch mais nous devons utiliser le catch/enfin, n'importe lequel d'entre eux. 2.Nous ne pouvons pas utiliser uniquement le bloc try.

0
Parmeshwar karale