ExceptionArgs.cs:
//异常信息基类 [Serializable] public abstract class ExceptionArgs { public virtual String Message { get { return String.Empty; } } }
泛型的异常类:
[Serializable] public sealed class Exception<TExceptionArgs>:Exception,System.Runtime.Serialization.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)); } //这个方法用于序列化,由于实现了ISerializable接口,所以它是公共的(该方法为ISerializable中定义的方法) //在Exception类中已有实现,此类继承了Exception,并重写了该方法在Exception中的实现 [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) ? base.Message : baseMsg + "(" + m_args.Message + ")"; } } public override bool Equals(object obj) { Exception<TExceptionArgs> other = obj as Exception<TExceptionArgs>; if (obj==null) { return false; } return Object.ReferenceEquals(m_args, other.m_args) && base.Equals(obj); } public override int GetHashCode() { return base.GetHashCode(); } }
注:C#只允许自定义的类继承自系统异常类的基类:System.Exception,并且继承自System.Exception类的所有异常类型,都必须是可被序列化的,这使得这些异常信息得以穿越AppDomain(比如Remoting服务端异常有可能需要返回到远程调用方,这时就不得不穿越AppDomain)或者写入日志/数据库等。
定义一个磁盘满的异常类:
//定义一个磁盘满的异常类 [Serializable] public sealed class DiskFullExceptionArgs:ExceptionArgs { //readonly:只读,动态常量,只能在构造器中被赋值 private readonly String m_diskpath; public DiskFullExceptionArgs(String diskpath) { m_diskpath = diskpath; } public String DiskPath { get { return m_diskpath; } } public override string Message { get { return (m_diskpath == null) ? base.Message : "DiskPath=" + m_diskpath; } } }
如果没有额外的数据要包含到类中,可以简单地写:
//定义一个磁盘满的异常类 [Serializable] public sealed class DiskFullExceptionArgs:ExceptionArgs { }
抛出/捕获自定义异常:
public void TestException() { try { throw new Exception<DiskFullExceptionArgs>( new DiskFullExceptionArgs(@"C:/"), "The disk is full"); } catch (Exception<DiskFullExceptionArgs> ex) { Console.WriteLine(ex.Message); } }