Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
En C#, les erreurs dans le programme au moment de l’exécution sont propagées via le programme à l’aide d’un mécanisme appelé exceptions. Les exceptions sont levées par le code qui rencontre une erreur et interceptées par le code qui peut corriger l’erreur. Les exceptions peuvent être levées par le runtime .NET ou par du code dans un programme. Une fois qu’une exception est levée, elle se propage dans la pile d'appels jusqu’à ce qu’une instruction catch
relative à l’exception soit trouvée. Les exceptions non interceptées sont gérées par un gestionnaire d’exceptions générique fourni par le système qui affiche une boîte de dialogue.
Les exceptions sont représentées par des classes dérivées de Exception. Cette classe identifie le type d’exception et contient des propriétés qui ont des détails sur l’exception. La levée d’une exception implique la création d’une instance d’une classe dérivée d’exception, la configuration facultative des propriétés de l’exception, puis la levée de l’objet à l’aide du throw
mot clé. Par exemple:
class CustomException : Exception
{
public CustomException(string message)
{
}
}
private static void TestThrow()
{
throw new CustomException("Custom exception in TestThrow()");
}
Une fois qu’une exception est levée, le runtime vérifie l’instruction actuelle pour voir s’il se trouve dans un try
bloc. Si c’est le cas, tous les catch
blocs associés au try
bloc sont vérifiés pour voir s’ils peuvent intercepter l’exception.
Catch
les blocs spécifient généralement des types d’exceptions ; si le type du catch
bloc est le même type que l’exception ou une classe de base de l’exception, le catch
bloc peut gérer la méthode. Par exemple:
try
{
TestThrow();
}
catch (CustomException ex)
{
System.Console.WriteLine(ex.ToString());
}
Si l’instruction qui lève une exception n’est pas dans un bloc try
ou si le bloc try
qui l’entoure n’a pas de bloc catch
correspondant, le runtime vérifie la méthode appelée pour une instruction try
et des blocs catch
. Le runtime continue jusqu’à la pile appelante, à la recherche d’un bloc catch
compatible. Une fois le bloc trouvé et exécuté, le contrôle est transféré à l'instruction qui suit ce bloc.
Une try
instruction peut contenir plusieurs catch
blocs. La première catch
instruction qui peut gérer l’exception est exécutée ; toutes les instructions suivantes catch
, même si elles sont compatibles, sont ignorées. Ordonnez les blocs catch du plus spécifique (ou plus dérivé) au moins spécifique. Par exemple:
using System;
using System.IO;
namespace Exceptions
{
public class CatchOrder
{
public static void Main()
{
try
{
using (var sw = new StreamWriter("./test.txt"))
{
sw.WriteLine("Hello");
}
}
// Put the more specific exceptions first.
catch (DirectoryNotFoundException ex)
{
Console.WriteLine(ex);
}
catch (FileNotFoundException ex)
{
Console.WriteLine(ex);
}
// Put the least specific exception last.
catch (IOException ex)
{
Console.WriteLine(ex);
}
Console.WriteLine("Done");
}
}
}
Avant l’exécution du catch
bloc, le runtime vérifie les finally
blocs. Les blocs Finally
permettent au programmeur de nettoyer tout état ambigu qui pourrait subsister après l’abandon d’un bloc try
, ou de libérer les ressources externes (telles que les handles graphiques, les connexions aux bases de données ou les flux de fichiers) sans attendre que le garbage collector du runtime finalise les objets. Par exemple:
static void TestFinally()
{
FileStream? file = null;
//Change the path to something that works on your machine.
FileInfo fileInfo = new System.IO.FileInfo("./file.txt");
try
{
file = fileInfo.OpenWrite();
file.WriteByte(0xF);
}
finally
{
// Closing the file allows you to reopen it immediately - otherwise IOException is thrown.
file?.Close();
}
try
{
file = fileInfo.OpenWrite();
Console.WriteLine("OpenWrite() succeeded");
}
catch (IOException)
{
Console.WriteLine("OpenWrite() failed");
}
}
Si WriteByte()
a levé une exception, le code du deuxième try
bloc qui tente de rouvrir le fichier échouerait si file.Close()
n’est pas appelé, et le fichier resterait verrouillé. Étant donné que finally
les blocs sont exécutés même si une exception est levée, le finally
bloc dans l’exemple précédent permet de fermer correctement le fichier et permet d’éviter une erreur.
Si aucun bloc compatible catch
n’est trouvé sur la pile des appels après la levée d’une exception, l’une des trois choses se produit :
- Si l’exception se trouve dans un finaliseur, le finaliseur est abandonné et le finaliseur de base, le cas échéant, est appelé.
- Si la pile des appels contient un constructeur statique ou un initialiseur de champ statique, une TypeInitializationException est levée, et l’exception d’origine est affectée à la propriété InnerException de la nouvelle exception.
- Si le début du thread est atteint, le thread est arrêté.