Что такое внутреннее исключение

Я прочитал MSDN, но я не мог понять эту концепцию.

Исправьте меня, если я ошибаюсь,

Функция innerexception будет использоваться в руке с текущим исключением.

Сначала будет происходить внутреннее исключение, а затем произойдет текущее исключение (если есть исключение), из-за которого InnerException проверяется на null. Чтобы сохранить внутреннее исключение, мы должны передать его как параметр.

Я прав с этим?

Ответ 1

Вы можете увидеть код ниже.

Первый шаг, я разбираю "abc" на целое число. Это вызовет FormatException.

В блоке catch я пытаюсь открыть текстовый файл для регистрации сообщения об исключении. Но этот файл не существует. FileNotFoundException будет повышен.

Я хочу знать, что вызвало второе исключение, поэтому я добавляю первое исключение (или FormatException) в конструктор второго исключения.

Теперь первое исключение - InnerException второго исключения.

В блоке catch я могу получить доступ к свойствам InnerException, чтобы узнать, что является первым исключением.

Это полезно?

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;
        }        
    }
}

Ответ 2

Внутреннее исключение - это исключение, вызвавшее текущее исключение.

Он используется в тех случаях, когда вы хотите получить другое исключение, кроме того, что ваш код поймал, но вы не хотите выбрасывать исходный контекст.

Чтобы новое исключение имело информацию о предыдущем, как вы сказали, вы передаете его как параметр конструктора в новый.

Обычно нулевое внутреннее исключение означает, что текущее исключение является основной причиной исключительной ситуации.

Ответ 3

Объекты исключений читаются только к тому времени, когда вы попадаете в блок catch, иногда ваш код не может ничего сделать для обработки исключения, но он может добавить дополнительную информацию, создав новое исключение и обернув исходное исключение внутри него. Это делает так, что вы можете добавлять информацию, но не обязательно копировать поле по полю каждую часть информации из исходного исключения (что может быть даже невозможно, если вы не знаете тип исключения, которое будет выбрано).

Вот немного модифицированный фрагмент из моего проекта, который использует немного всего, что связано с Исключениями.

    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; }
    }
}