【问题标题】:What is inner Exception什么是内部异常
【发布时间】:2014-05-14 14:22:30
【问题描述】:

我已经阅读了 MSDN,但是我无法理解这个概念。

如果我错了,请纠正我,

内部异常将与当前异常一起使用。

首先发生内部异常,然后发生当前异常(如果有异常),这就是为什么要检查 InnerExceptionnull 的原因。为了保留内部异常,我们必须将其作为参数传递。

我说得对吗?

【问题讨论】:

  • 所以您通常只对内部异常感兴趣,但请注意,它也可能有其内部异常。您可能想要滚动自己的例程来查找 InnerMost 异常。
  • 也许得到根异常,即可能有多个内部异常... while (ex.InnerException != null) ex = ex.InnerException;
  • 关于这个主题的很好的教程,来自优秀的 Kudvenkat,供偶然发现这个问题的人使用:youtube.com/watch?v=MO3sOTWfZPc
  • 异常中的异常。我喜欢称它为InCeption。

标签: c# .net exception inner-exception


【解决方案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"); // Throws FormatException               
            }
            catch ( FormatException fe )
            {
                try
                {
                    var openLog = File.Open("DoesNotExist", FileMode.Open);
                }
                catch
                {
                    throw new FileNotFoundException("NestedExceptionMessage: File `DoesNotExist` not found.", fe );
                }                              
            }
        }
        // Consider what exception is thrown: FormatException or FileNotFoundException?
        catch ( FormatException fe)
        {
            // FormatException isn't caught because it's stored "inside" the FileNotFoundException
        }
        catch ( FileNotFoundException fnfe ) 
        {
            string inMes="", outMes;
            if (fnfe.InnerException != null)
                inMes = fnfe.InnerException.Message; // Inner exception (FormatException) message
            outMes = fnfe.Message;
            Console.WriteLine($"Inner Exception:\n\t{inMes}");
            Console.WriteLine($"Outter Exception:\n\t{outMes}");
        }        
    }
}

控制台输出

Inner Exception:
    Input string was not in a correct format.
Outter Exception:
    NestedExceptionMessage: File `DoesNotExist` not found.

外部异常是指嵌套最深的异常,最终抛出。 内部异常是指最浅的(在范围内)异常。

【讨论】:

  • 外深内浅如何?不应该反过来吗?
【解决方案2】:

内部异常是导致当前异常的异常。

当您想要显示与您的代码捕获的异常不同的异常但又不想丢弃原始上下文的情况下使用它。

如您所说,为了让新异常获得有关前一个异常的信息,您将其作为构造函数参数传递给新异常。

通常,null 内部异常意味着当前异常是异常情况的根本原因。

【讨论】:

    【解决方案3】:

    异常对象仅在您到达catch 块时才被读取,有时您的代码无法处理异常,但它可以通过创建新异常并包装最初抛出的异常来添加更多信息在里面。这使得您可以添加信息,但不需要逐个字段地复制原始异常中的每条信息(如果您不知道将引发的异常类型,这甚至可能是不可能的)。

    这是我的一个项目中经过稍微修改的 sn-p,它使用了一些处理异常的东西。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-25
      • 1970-01-01
      • 1970-01-01
      • 2011-12-12
      • 1970-01-01
      相关资源
      最近更新 更多