• CLR via C# 笔记 -- 异常和状态管理(20)


    1. 异常是指成员没有完成它的名称所宣称的行动,异常类继承System.Exception。

    2. .Net Framework 异常处理机制是用Microsoft windows提供的结构化异常处理(Structured Exception Handing, SEH)机制构建的。

    3. AppDomain的FirstChanceException事件登记,只要AppDomain发生异常,就会收到通知,通知是在CLR开始搜索任何catch快之前发生的。

    4. 由于其他语言不一定要继承Exception,CLR 2.0引入System.Runtime.ComplierServices.RuntimeWrappedException 对其他语言进行包装。

    5. System.Exception属性

      1) Message:包含辅助性文字说明,指出抛出异常的原因。如果抛出的异常未处理,该消息通常被写入日志。由于最终用户一般不看这种消息,所以消息应提供尽可能多的技术细节。

      2) Data:键值对集合,代码抛出异常前在该集合中添加记录项;捕捉异常的代码可在异常恢复过程中查询记录项并利用其中信息。

      3) Source:包含生成异常的程序集的名称。

      4) StackTrace:包含抛出异常之前调用过的所有方法的名称和签名,该属性对调试很有用。

      5) InnerException:如果当前异常是在处理一个异常时抛出的。该属性就指出上一个异常是什么。这个只读属性通常为null。Exception类型还提供了公共方法GetBaseException来遍历由内层异常构成的链表

    6. 重新抛出异常

    try { ... }
    catch (Exception e) 
    {
        ...
        throw e; // CLR 认为这是异常的起点
    }
    try { ... }
    catch (Exception e) 
    {
        ...
        throw; // 不影响CLR对异常起点的认知。FxCop不再报错
    }

    7. 如果能找到你的程序集的调用符合(存储在.pdb文件中),那么在System.Exception的StackTrace属性或者System.Diagnostics.StackTrace的Tostring()方法返回的字符串中,将包括源代码文件路径和代码行号,这些信息对于调试是很有用的。

    8. [assembly: System.Diagnostics.Debuggable(System.Diagnostics.DebuggableAttribute.DebuggingModes.DisableOptimizations)] JIT编译器不会对程序集的方法进行内联。

    9. [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 禁止JIT编译器在调试和发布生成(debug and release build)时对该方法进行内联处理。

    10. 定义异常类 1). 尽量创建少的基类。原因是基类的主要作用就是将大量错误当作一个错误,而这通常是危险的。基于同样的考虑,永远都不要抛出一个System.Exception对象,抛出其他任何基类异常类型时也要特别谨慎。

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                throw new Exception<DiskFullExceptionArgs>(new DiskFullExceptionArgs("C:/"), "The disk is full");
            }
            catch (Exception<DiskFullExceptionArgs> e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
    
    [Serializable]
    public sealed class Exception<TExceptionArgs> : Exception, ISerializable 
        where TExceptionArgs : ExceptionArgs
    {
        private const string c_args = "Args"; // 用于(反)序列化
        private readonly TExceptionArgs m_args;
        public TExceptionArgs Args { get { return m_args; } }
            
        public Exception(string message = null, Exception innerException = null) 
            :this(null, message, innerException)
        {
    
        }
    
        public Exception(TExceptionArgs args, string msssage = null, Exception innerException = null)
            :base (msssage, innerException)
        {
            m_args = args;
        }
    
        // 这个构造器用于反序列化;由于类是密封的,所以构造器是私有的
        // 如果这个类不是密封的,这个构造器就应该是受保护的
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        private Exception(SerializationInfo info, StreamingContext context) 
            : base(info, context)
        {
            m_args = (TExceptionArgs)info.GetValue(c_args, typeof(TExceptionArgs));
        }
    
        // 这个方法用于序列化;由于 ISerializable 接口,所以它是公共的
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue(c_args, m_args);
            base.GetObjectData(info, context);
        }
    
        public override string Message 
        {
            get 
            {
                string baseMsg = base.Message;
                return (m_args == null) ? baseMsg : baseMsg + "(" + m_args.Message + ")";
            }
        }
    
        public override bool Equals(object obj)
        {
            Exception<TExceptionArgs> other = obj as Exception<TExceptionArgs>;
            if (other == null) return false;
            return Object.Equals(m_args, other.m_args) && base.Equals(obj);
        }
    
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
    }
    
    [Serializable]
    public abstract class ExceptionArgs 
    {
        public virtual string Message { get { return string.Empty; } }
    }
    
    /// <summary>
    /// 代表磁盘满的异常类
    /// </summary>
    [Serializable]
    public sealed class DiskFullExceptionArgs : ExceptionArgs 
    {
        private readonly string m_diskpath; // 在构造时设置的私有字段
    
        public DiskFullExceptionArgs(string diskpath) 
        {
            m_diskpath = diskpath;
        }
    
        // 返回字段的公共只读属性
        public string DiskPath { get { return m_diskpath; } }
    
        public override string Message => m_diskpath == null ? base.Message : "DiskPath=" + m_diskpath;
    }
  • 相关阅读:
    [.NET控件]Telerik RadControls for ASP.NET AJAX 2008 Q1 net 2.0 Web.UI
    Cookie对象实战
    怎么样修改地址栏前面的图标
    进程管理工具可以下载使用
    怎样才能实现表格背景图片拉伸
    TabControl控件的最佳实践,可以把一个窗体和用户控件添加进来
    flex+eclipse
    为gridview“删除”列添加确认对话框的方法
    触发器deleted 表和 inserted 表详解!!!
    ExtJs的使用
  • 原文地址:https://www.cnblogs.com/Cxiaoao/p/14846528.html
Copyright © 2020-2023  润新知