I have read the MSDN but, I could not understand this concept.
Correct me if I am wrong,
A innerexception will be used in hand with current exception.
Inner exception will occur first and then the current exception will occur (if there is an exception) that is the reason why InnerException
is checked against null
. In order to retain inner exception we have to pass it as a parameter.
Am I right with this?
You can see the code below.
First step, i parse "abc" to integer. It will raise FormatException.
In catch block, i try to open text file to log exception message. But this file didn't exist. FileNotFoundException will be raise.
I want to know what raise the second exception, so i add the first exception (or FormatException) to constructor of the second exception.
Now the first exception is InnerException of the second exception.
In catch block, i can access InnerException properties to know what is the first exception.
It's useful?
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;
}
}
}
An inner exception is the exception that caused the current exception.
It is used in cases when you want to surface a different exception than the one that your code caught but you don't want to throw away the original context.
In order for a new exception to have information about a previous one, like you said, you pass it as constructor parameter to the new one.
Usually, a null inner exception means that the current exception is root cause of the exceptional situation.
Exception objects are read only by the time you get to a catch
block, sometimes your code can't do anything to handle the exception, but it can add more information by creating a new exception and wrapping the originally thrown exception inside of it. This makes it so you can add information but not be required to copy field by field every piece of information from the original exception (which may not even be possible if you don't know the type of exception that will be thrown).
Here is a slightly modified snippet from a project of mine that uses a bit of everything dealing with 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; }
}
}
来源:https://stackoverflow.com/questions/22826067/what-is-inner-exception