C#自定义异常类型(摘自CLRViaC#3thEdition)



 

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


 

 

 



版权声明:本文为博主原创文章,未经博主允许不得转载。