clr via c# 异常和状态管理
1,System.Exception 类---所有异常类的基类
|
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()); } }
- 给出测试结果
- 由此我们可以看出,InnerException,是通过Throw方法在Catch块中传递的.类似
- Exception.GetBaseException
- 定义最先抛出的异常---最Base,最底部;最后抛出的异常---Current,最顶部.
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
static void Rethrow() { try { DivideBy0(); } catch (Exception ex) { throw new ThirdLevelException( "Caught the second exception and " + "threw a third in response.", ex); } }
ex.GetBaseException().ToString());//获取Exception链表的最先抛出的异常.越后面抛出的越前面.
2,自定义异常类及其使用方法:
- 定义一个自定义的异常类
[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(); } }
- 该异常类继承了Exception和Iserializable.并且实现了类的序列化和反序列化
- 该类可以携带一个参数类信息.
[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:\