J'ai lu le MSDN mais je ne pouvais pas comprendre ce concept.
Corrigez-moi si je me trompe,
Une innerexception sera utilisée à la main avec l'exception actuelle.
L'exception interne se produira d'abord, puis l'exception actuelle se produira (s'il y a une exception), c'est la raison pour laquelle InnerException
est comparé à null
. Afin de conserver l'exception interne, nous devons la passer en paramètre.
Suis-je d'accord avec ça?
Vous pouvez voir le code ci-dessous.
Première étape, j'analyse "abc" en entier. Cela lèvera FormatException.
Dans le bloc catch, j'essaie d'ouvrir un fichier texte pour enregistrer le message d'exception. Mais ce fichier n'existait pas. FileNotFoundException sera levée.
Je veux savoir ce qui a déclenché la deuxième exception, alors j'ajoute la première exception (ou FormatException) au constructeur de la deuxième exception.
Maintenant, la première exception est InnerException de la deuxième exception.
Dans le bloc catch, je peux accéder aux propriétés d'InnerException pour savoir quelle est la première exception.
Est-ce utile?
using System;
using System.IO;
public class Program
{
public static void Main( )
{
try
{
try
{
var num = int.Parse("abc");
}
catch ( Exception inner )
{
try
{
var openLog = File.Open("DoesNotExist", FileMode.Open);
}
catch
{
throw new FileNotFoundException("OutterException", inner);
}
}
}
catch ( Exception e)
{
string inMes, outMes;
if (e.InnerException != null)
inMes = e.InnerException.Message;
outMes = e.Message;
}
}
}
Une exception interne est l'exception qui a provoqué l'exception actuelle.
Il est utilisé dans les cas où vous souhaitez faire apparaître une exception différente de celle que votre code a interceptée mais que vous ne voulez pas jeter le contexte d'origine.
Pour qu'une nouvelle exception contienne des informations sur une précédente, comme vous l'avez dit, vous la passez en tant que paramètre constructeur à la nouvelle.
Généralement, une exception interne nulle signifie que l'exception actuelle est la cause première de la situation exceptionnelle.
Les objets d'exception sont lus uniquement au moment où vous arrivez à un bloc catch
, parfois votre code ne peut rien faire pour gérer l'exception, mais il peut ajouter plus d'informations en créant une nouvelle exception et en encapsulant l'exception initialement levée à l'intérieur. Cela vous permet d'ajouter des informations sans être obligé de copier champ par champ chaque élément d'information de l'exception d'origine (ce qui peut même ne pas être possible si vous ne connaissez pas le type d'exception qui sera levée).
Voici un extrait légèrement modifié d'un de mes projets qui utilise un peu de tout ce qui concerne les exceptions.
private void SomeFunction(string username, string password)
{
try
{
try
{
_someObject.DoSpecialPrivilegedFunction(username, password);
}
catch (UnauthorizedAccessException ex)
{
throw new UserUnauthorizedException(username, "DoSpecialPrivilegedFunction", ex);
}
catch (IOException ex)
{
throw new UserModuleActionException("A network IO error happend.", username, "DoSpecialPrivilegedFunction", ex);
}
//Other modules
}
catch (Exception ex)
{
//If it is one of our custom expections, just re-throw the exception.
if (ex is UserActionException)
throw;
else
throw new UserActionException("A unknown error due to a user action happened.", username, ex);
}
}
//elsewhere
[Serializable]
public class UserUnauthorizedException : UserModuleActionException
{
private const string DefaultMessage = "The user attempted to use a non authorized module";
public UserUnauthorizedException()
: base(DefaultMessage)
{
}
public UserUnauthorizedException(string message)
: base(message)
{
}
public UserUnauthorizedException(string message, Exception innerException)
: base(message, innerException)
{
}
public UserUnauthorizedException(string username, string module, Exception innerException = null) : base(DefaultMessage, username, module, innerException)
{
}
protected UserUnauthorizedException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
[Serializable]
public class UserModuleActionException : UserActionException
{
private readonly string _module;
public UserModuleActionException()
{
}
public UserModuleActionException(string message) : base(message)
{
}
public UserModuleActionException(string message, Exception innerException) : base(message, innerException)
{
}
public UserModuleActionException(string message, string username, string module, Exception innerException = null)
: base(message, username, innerException)
{
_module = module;
}
protected UserModuleActionException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public virtual string Module
{
get { return _module; }
}
public override string Message
{
get
{
string s = base.Message;
if (!String.IsNullOrEmpty(_module))
{
return s + Environment.NewLine + String.Format("Module: {0}", _module);
}
return base.Message;
}
}
}
[Serializable]
public class UserActionException : Exception
{
private readonly string _username;
public UserActionException()
{
}
public UserActionException(string message)
: base(message)
{
}
public UserActionException(string message, Exception innerException)
: base(message, innerException)
{
}
public UserActionException(string message, string username, Exception innerException = null)
: base(message, innerException)
{
_username = username;
}
protected UserActionException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
public override string Message
{
get
{
string s = base.Message;
if (!String.IsNullOrEmpty(_username))
{
return s + Environment.NewLine + String.Format("Username: {0}", _username);
}
return base.Message;
}
}
public virtual string Username
{
get { return _username; }
}
}