clr via c# 异常和状态管理

1,System.Exception 类---所有异常类的基类

Message

readonly string 指出异常的原因
Data readonly IDictionary 引用一个键值对集合
Source r/w string 包含异常的程序集名称
StackTrace r string 包含异常之前调用所有方法和信息
TargetSite r MethodBase 包含抛出异常的方法
InnerException r Exception

如果当前异常时在处理一个异常时抛出的,则指出上个异常是什么

可以使用Exception.GetBaseException来遍历异常链表.

HResult r/w int COM api 返回值维护.

1.1    Exception.GetBaseException 方法用法

  •         首先创建两个异常类用于重新抛出:
class SecondLevelException : Exception
    {
        public SecondLevelException(string message, Exception inner)//使用Message和InnerExciption来初始化异常
            : base(message, inner)
        { }
    }
    class ThirdLevelException : Exception//使用Message和InnerExciption来初始化异常
    {
        public ThirdLevelException(string message, Exception inner)
            : base(message, inner)
        { }
    }
  
  •       其次,创建用于抛出异常的行为方法:
    • static void DivideBy0()
              {
                  try
                  {
                      int zero = 0;
                      int ecks = 1 / zero;
                  }
                  catch (Exception ex)
                  {
                      throw new SecondLevelException(
                          "Forced a division by 0 and threw " +
                          "a second exception.", ex);
                  }
              }
      static void Rethrow()
              {
                  try
                  {
                      DivideBy0();
                  }
                  catch (Exception ex)
                  {
                      throw new ThirdLevelException(
                          "Caught the second exception and " +
                          "threw a third in response.", ex);
                  }
              }
  •     创建测试方法:
    •  public static void Go()
              {
      
      
                  try
                  {
                      // This function calls another that forces a 
                      // division by 0.
                      Rethrow();
                  }
                  catch (Exception ex)
                  {
                      Exception current;
      
      
                      // This code unwinds the nested exceptions using the 
                      // InnerException property.
                      current = ex;
                      while (current != null)
                      {
                          Console.WriteLine(current.ToString());
                          Console.WriteLine();
                          current = current.InnerException;//调用当前异常的上个异常.
                      }
      
                      // Display the innermost exception.
                      Console.WriteLine(
                          "Display the base exception " +
                          "using the GetBaseException method:\n");
                      Console.WriteLine(
                          ex.GetBaseException().ToString());
                  }
              }


  • 给出测试结果
  • ClrFromCSharp_2_2.LearnException.ThirdLevelException: Caught the second exception and threw a third in response. ---> ClrFromCSharp_2_2.LearnException.SecondLevelException: Forced a division by 0 and threw a second exception. ---> System.DivideByZeroException: 尝试除以零。
       在 ClrFromCSharp_2_2.LearnException.ExceptionRef.DivideBy0() 位置 C:\reps\ClrFromCSharp\ClrFromCSharp_2_2\LearnException\ExceptionRef.cs:行号 62
       --- 内部异常堆栈跟踪的结尾 ---
       在 ClrFromCSharp_2_2.LearnException.ExceptionRef.DivideBy0() 位置 C:\reps\ClrFromCSharp\ClrFromCSharp_2_2\LearnException\ExceptionRef.cs:行号 66
       在 ClrFromCSharp_2_2.LearnException.ExceptionRef.Rethrow() 位置 C:\reps\ClrFromCSharp\ClrFromCSharp_2_2\LearnException\ExceptionRef.cs:行号 48
       --- 内部异常堆栈跟踪的结尾 ---
       在 ClrFromCSharp_2_2.LearnException.ExceptionRef.Rethrow() 位置 C:\reps\ClrFromCSharp\ClrFromCSharp_2_2\LearnException\ExceptionRef.cs:行号 52
       在 ClrFromCSharp_2_2.LearnException.ExceptionRef.Go() 位置 C:\reps\ClrFromCSharp\ClrFromCSharp_2_2\LearnException\ExceptionRef.cs:行号 19---从最初异常---至抛出异常的一个trace.
    
    ClrFromCSharp_2_2.LearnException.SecondLevelException: Forced a division by 0 and threw a second exception. ---> System.DivideByZeroException: 尝试除以零。
       在 ClrFromCSharp_2_2.LearnException.ExceptionRef.DivideBy0() 位置 C:\reps\ClrFromCSharp\ClrFromCSharp_2_2\LearnException\ExceptionRef.cs:行号 62
       --- 内部异常堆栈跟踪的结尾 ---
       在 ClrFromCSharp_2_2.LearnException.ExceptionRef.DivideBy0() 位置 C:\reps\ClrFromCSharp\ClrFromCSharp_2_2\LearnException\ExceptionRef.cs:行号 66
       在 ClrFromCSharp_2_2.LearnException.ExceptionRef.Rethrow() 位置 C:\reps\ClrFromCSharp\ClrFromCSharp_2_2\LearnException\ExceptionRef.cs:行号 48//从最初异常到抛出异常的一个base.
    
    System.DivideByZeroException: 尝试除以零。
       在 ClrFromCSharp_2_2.LearnException.ExceptionRef.DivideBy0() 位置 C:\reps\ClrFromCSharp\ClrFromCSharp_2_2\LearnException\ExceptionRef.cs:行号 62//从最初异常到抛出异常的一个base.
    
    Display the base exception using the GetBaseException method:
    
    System.DivideByZeroException: 尝试除以零。
       在 ClrFromCSharp_2_2.LearnException.ExceptionRef.DivideBy0() 位置 C:\reps\ClrFromCSharp\ClrFromCSharp_2_2\LearnException\ExceptionRef.cs:行号 62//最底层的一个ex
    • 由此我们可以看出,InnerException,是通过Throw方法在Catch块中传递的.类似
    • static void Rethrow()
              {
                  try
                  {
                      DivideBy0();
                  }
                  catch (Exception ex)
                  {
                      throw new ThirdLevelException(
                          "Caught the second exception and " +
                          "threw a third in response.", ex);
                  }
              }
    • Exception.GetBaseException
    • ex.GetBaseException().ToString());//获取Exception链表的最先抛出的异常.越后面抛出的越前面.
    • 定义最先抛出的异常---最Base,最底部;最后抛出的异常---Current,最顶部.

2,自定义异常类及其使用方法:

  1.            定义一个自定义的异常类


[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 message=null,Exception innerException = null) : base(message, 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));
        }
        [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 : string.Format("{0} ({1})", 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();
        }
    }
  1. 该异常类继承了Exception和Iserializable.并且实现了类的序列化和反序列化
  2. 该类可以携带一个参数类信息.
[Serializable]
    public abstract class ExceptionArgs
    {
        public virtual String Message { get { return string.Empty; } }
    }


3,建立自己的ExceptionArgs的派生类,用于携带异常信息.

public sealed class DiskFullExceptionArgs : ExceptionArgs
    {
        public string Path { get; }
        public DiskFullExceptionArgs(string path)
        {
            Path = path;
        }
        public override string Message => Path ?? base.Message;
    }

    4,使用方法:

 public static void GoCustomException()
        {
            try
            {
                throw new Exception<DiskFullExceptionArgs>(new DiskFullExceptionArgs(@"c:\"), "disk is full");
            }
            catch(Exception<DiskFullExceptionArgs> e)
            {
                Console.WriteLine("the Exception Message is {0}", e.Message);//调用类e.Message
                Console.WriteLine("the ExceptionArgs Message is {0}", e.Args.Message);//调用类e.Args.Message
            }
        }

     5,结果

the Exception Message is disk is full (c:\)
the ExceptionArgs Message is c:\

猜你喜欢

转载自www.cnblogs.com/frogkiller/p/12291485.html