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é?
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.
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.
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
Parce que finalement sera exécuté même si vous ne gérez pas une exception dans un bloc catch.
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
}
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.
je vais expliquer l'utilisation de finalement avec un exception de lecteur de fichier Exemple
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.
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.
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.
}
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.
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.
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
}
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
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.
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
.
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 Try
… Catch
. 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.