web-dev-qa-db-fra.com

Pourquoi utiliser finalement en C #?

Ce qui est finalement dans les blocs est exécuté (presque) toujours, alors quelle est la différence entre y inclure du code et le laisser non fermé?

178
Rodrigo

Le code à l'intérieur d'un bloc finally sera exécuté, qu'il y ait ou non une exception. Cela s'avère très utile pour certaines fonctions de maintenance dont vous avez toujours besoin pour fonctionner comme si vous étiez en train de fermer des connexions.

Maintenant, je devinant votre question est pourquoi vous devriez faire ceci:

try
{
    doSomething();
}
catch
{
    catchSomething();
}
finally
{
    alwaysDoThis();
}

Quand tu peux faire ça:

try
{
    doSomething();
}
catch
{
    catchSomething();
}

alwaysDoThis();

La réponse est que très souvent, le code contenu dans votre instruction catch renverra une exception ou sortira de la fonction actuelle. Avec ce dernier code, le "alwaysDoThis ();" call ne sera pas exécuté si le code contenu dans l'instruction catch génère un retour ou lève une nouvelle exception.

381
Kevin Pang

La plupart des avantages d'utiliser try-finally ont déjà été signalés, mais je pensais ajouter celui-ci:

try
{
    // Code here that might throw an exception...

    if (arbitraryCondition)
    {
        return true;
    }

    // Code here that might throw an exception...
}
finally
{
    // Code here gets executed regardless of whether "return true;" was called within the try block (i.e. regardless of the value of arbitraryCondition).
}

Ce comportement le rend très utile dans diverses situations, en particulier lorsque vous devez effectuer un nettoyage (disposer des ressources), bien qu'un bloc tilisation soit souvent préférable dans ce cas.

59
Noldorin

chaque fois que vous utilisez des requêtes de code non gérées telles que des lecteurs de flux, des requêtes de base de données, etc. et vous voulez attraper l'exception puis utilisez try attachez enfin et fermez le flux, le lecteur de données, etc. Enfin, si vous ne le faites pas, la connexion ne sera pas fermée, c'est vraiment mauvais avec les requêtes de base de données

 SqlConnection myConn = new SqlConnection("Connectionstring");
        try
        {
            myConn.Open();
            //make na DB Request                
        }
        catch (Exception DBException)
        {
            //do somehting with exception
        }
        finally
        {
           myConn.Close();
           myConn.Dispose();
        }

si vous ne voulez pas attraper l'erreur, utilisez

 using (SqlConnection myConn = new SqlConnection("Connectionstring"))
        {
            myConn.Open();
            //make na DB Request
            myConn.Close();
        }

et l'objet de connexion sera automatiquement éliminé s'il y a une erreur, mais vous ne capturez pas l'erreur

11
Bob The Janitor

Parce que finalement sera exécuté même si vous ne gérez pas une exception dans un bloc catch.

10
Matt Briggs

Enfin, les instructions peuvent être exécutées même après le retour.

private int myfun()
{
    int a = 100; //any number
    int b = 0;
    try
    {
        a = (5 / b);
        return a;
    }
    catch (Exception ex)
    {
        Response.Write(ex.Message);
        return a;
    }

 //   Response.Write("Statement after return before finally");  -->this will give error "Syntax error, 'try' expected"
    finally
    {
      Response.Write("Statement after return in finally"); // --> This will execute , even after having return code above
    } 

    Response.Write("Statement after return after finally");  // -->Unreachable code
}
7
Prateek Gupta

finally, comme dans:

try {
  // do something risky
} catch (Exception ex) {
  // handle an exception
} finally {
  // do any required cleanup
}

est une opportunité garantie d’exécuter du code après votre try..catch block, que votre bloc try lève ou non une exception.

Cela le rend parfait pour des choses comme la libération de ressources, les connexions à la base de données, les descripteurs de fichiers, etc.

7
David Alpert

je vais expliquer l'utilisation de finalement avec un exception de lecteur de fichier Exemple

  • sans utiliser enfin
try{

  StreamReader strReader = new StreamReader(@"C:\Ariven\Project\Data.txt");
  Console.WriteLine(strReader.ReadeToEnd());
  StreamReader.Close();
}
catch (Exception ex)
{
  Console.WriteLine(ex.Message);
}

dans l'exemple ci-dessus, si le fichier appelé Data.txt est manquant, une exception sera levée et sera gérée mais le L'instruction appelée StreamReader.Close(); ne sera jamais exécutée.
Pour cette raison, les ressources associées au lecteur n'ont jamais été publiées.

  • Pour résoudre le problème ci-dessus, nous utilisons finalement
StreamReader strReader = null;
try{
    strReader = new StreamReader(@"C:\Ariven\Project\Data.txt");
    Console.WriteLine(strReader.ReadeToEnd());
}
catch (Exception ex){
    Console.WriteLine(ex.Message);
}
finally{
    if (strReader != null){
        StreamReader.Close();
    }
}

Bonne codage :)

Note: "@" est utilisé pour créer une chaîne mot à mot, afin d'éviter une erreur de "Séquence d'échappement non reconnue". Le symbole @ signifie lire littéralement cette chaîne et ne pas interpréter les caractères de contrôle autrement.

3
Ariven Nadar

En utilisant un bloc finally, vous pouvez nettoyer toutes les ressources allouées dans un bloc try et exécuter du code même si une exception se produit dans le bloc try. Généralement, les instructions d'un bloc finally sont exécutées lorsque le contrôle laisse une instruction try. Le transfert de contrôle peut survenir à la suite d'une exécution normale, de l'exécution d'un break, continue, goto, or return déclaration, ou de propagation d'une exception en dehors de l'instruction try.

Dans une exception gérée, l'exécution du bloc finally associé est garantie. Toutefois, si l'exception n'est pas gérée, l'exécution du bloc finally dépend de la façon dont l'opération de dérogation d'exception est déclenchée. Cela dépend de la configuration de votre ordinateur. Pour plus d'informations, voir Traitement des exceptions non gérées dans le CLR .

Habituellement, lorsqu'une exception non gérée termine une application, que le bloc finally soit exécuté ou non est sans importance. Toutefois, si vous avez des instructions dans un bloc finally qui doivent être exécutées même dans cette situation, une solution consiste à ajouter un bloc catch à l'élément try-finally déclaration. Alternativement, vous pouvez intercepter l’exception qui pourrait être levée dans le bloc try d’un try-finally instruction plus haut dans la pile d’appel. En d’autres termes, vous pouvez intercepter l’exception dans la méthode qui appelle la méthode contenant le try-finally, ou dans la méthode qui appelle cette méthode, ou dans n’importe quelle méthode de la pile d’appels. Si l'exception n'est pas interceptée, l'exécution du bloc finally dépend du choix du système d'exploitation de déclencher une opération de déroulement de l'exception.

public class ThrowTestA
{
    static void Main()
    {
        int i = 123;
        string s = "Some string";
        object obj = s;

        try
        {
            // Invalid conversion; obj contains a string, not a numeric type.
            i = (int)obj;

            // The following statement is not run.
            Console.WriteLine("WriteLine at the end of the try block.");
        }
        finally
        {
            // To run the program in Visual Studio, type CTRL+F5. Then  
            // click Cancel in the error dialog.
            Console.WriteLine("\nExecution of the finally block after an unhandled\n" +
                "error depends on how the exception unwind operation is triggered.");
            Console.WriteLine("i = {0}", i);
        }
    }
    // Output: 
    // Unhandled Exception: System.InvalidCastException: Specified cast is not valid. 
    // 
    // Execution of the finally block after an unhandled 
    // error depends on how the exception unwind operation is triggered. 
    // i = 123
}

Dans l'exemple suivant, une exception de la méthode TryCast est interceptée dans une méthode plus loin dans la pile d'appels. C #

public class ThrowTestB
{
    static void Main()
    {
        try
        {
            // TryCast produces an unhandled exception.
            TryCast();
        }
        catch (Exception ex)
        {
            // Catch the exception that is unhandled in TryCast.
            Console.WriteLine
                ("Catching the {0} exception triggers the finally block.",
                ex.GetType());

            // Restore the original unhandled exception. You might not 
            // know what exception to expect, or how to handle it, so pass  
            // it on. 
            throw;
        }
    }

    public static void TryCast()
    {
        int i = 123;
        string s = "Some string";
        object obj = s;

        try
        {
            // Invalid conversion; obj contains a string, not a numeric type.
            i = (int)obj;

            // The following statement is not run.
            Console.WriteLine("WriteLine at the end of the try block.");
        }
        finally
        {
            // Report that the finally block is run, and show that the value of 
            // i has not been changed.
            Console.WriteLine("\nIn the finally block in TryCast, i = {0}.\n", i);
        }
    }
    // Output: 
    // In the finally block in TryCast, i = 123. 

    // Catching the System.InvalidCastException exception triggers the finally block. 

    // Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
}
3
Alex Jolig

Supposons que vous deviez redéfinir le curseur sur le pointeur par défaut au lieu d'un curseur en attente (sablier). Si une exception est levée avant de définir le curseur et ne bloque pas directement l'application, vous risquez de vous retrouver avec un curseur confus.

2
Chris Doggett

Le bloc finally est utile pour nettoyer toutes les ressources allouées dans le bloc try et pour exécuter tout code qui doit être exécuté, même en cas d'exception. Le contrôle est toujours passé au bloc finally quelle que soit la façon dont le bloc try se termine.

2
cgreeno

Parfois, vous ne voulez pas gérer une exception (pas de bloc catch), mais vous voulez que du code de nettoyage soit exécuté.

Par exemple:

try
{
    // exception (or not)
}
finally
{
    // clean up always
}
2
markom

Le flux de contrôle du bloc Finally se situe après le bloc try ou Catch.

[1. First Code]
[2. Try]
[3. Catch]
[4. Finally]
[5. After Code]

avec Exception 1> 2> 3> 4> 5 si 3 a une déclaration de retour 1> 2> 3> 4

sans exception 1> 2> 4> 5 si 2 a une déclaration de retour 1> 2> 4

1
Ranald Fong

Ahh ... Je pense que je vois ce que vous dites! Tu m'as pris une seconde ... tu te demandes "pourquoi le placer dans le bloc finally plutôt qu'après le dernier bloc et complètement en dehors du try-catch-finally".

Par exemple, cela peut être dû au fait que vous arrêtez l’exécution si vous générez une erreur, mais vous souhaitez toujours nettoyer les ressources, telles que les fichiers ouverts, les connexions à la base de données, etc.

1
Beska

Comme mentionné dans le documentation :

Une utilisation courante de catch et de la combinaison consiste à obtenir et à utiliser des ressources dans un bloc try, à gérer des circonstances exceptionnelles dans un bloc catch et à libérer les ressources du dernier bloc.

Cela vaut également la peine de lire this , qui dit:

Une fois qu'une clause catch correspondante est trouvée, le système se prépare à transférer le contrôle vers le premier énoncé de la clause catch. Avant que l'exécution de la clause catch ne commence, le système exécute d'abord, dans l'ordre, toutes les clauses finally associées aux instructions try plus imbriquées que celles ayant intercepté l'exception.

Il est donc clair que le code qui réside dans une clause finally sera exécuté même si une clause antérieure catch avait une instruction return.

0
Nexaspx

enfin bloqué

Si vous avez une ou plusieurs instructions à exécuter avant de quitter la structure Try, utilisez un bloc Finally. Un bloc Finally est utile pour exécuter tout code qui doit être exécuté même s'il existe une exception. Le contrôle est passé au bloc Finally, quel que soit le mode de fermeture du bloc Try...Catch. Le contrôle passe au bloc Finally juste avant de sortir de la structure TryCatch. Cela est vrai même si une exception se produit n'importe où dans la structure Try. Le code d'un bloc Finally est exécuté même si votre code rencontre une instruction Return dans un bloc Try ou Catch.

Il n'est pas valide de transférer explicitement l'exécution dans un bloc Finally.

Le transfert de l'exécution hors d'un bloc Finally n'est pas valide, sauf par le biais d'une exception.

0
Neoheurist