定义自己的异常类
当抛出一个异常类型时,建议抛出一个具体的异常类型,即一个没有其他类继承的异常类型。例如不要抛出ArgumentException,因为它是三个异常类的基类,表示的意思不是很清楚,永远不应该抛出Exception,Application或者SystemException类型(kao,我经常抛出Exception,杯具);
通过抛出一个自定义的异常类型实例可以使捕获代码精确地知道所发生的事情,并以合适的方式进行恢复;定义自己的异常时,可以自由的定义自己的子层次结构,作为一个层次结构应该宽而且浅:异常类型应该继承自一个与Exception相近的类型,并且继承深度一般不应该超过2到3层。如果不打算作为基类,应该将其标识为sealed。
Exception即类型定义了三个公有构造器:
- 无参构造器,它创建一个异常类型的实例,并将所有的字段和属性设为默认值。
- 一个参数为string的构造器,它创建一个异常类型的实例,并将异常的消息文本设置为指定的字符串。
- 一哥 参数为string和Exception的构造器,它创建一个异常类型的势力,并将异常消息文本和内部异常分别设为构造器参数中制定的string和Exception。
自定义异常会继承Exception中定义的字段和属性,当然可以加入自己的字段和属性。
所有的异常类型都应该是可序列化的,因为只有这样异常才能够在跨应用程序域或机器边界是封送处理、并在客户端重新抛出(Serializable特性),并且如果类型定义了如何新的字段,还必须让其实现ISerializable接口的GetObjectData方法和一个特殊的受保护的构造器(这一段话没有懂);
一个自定义的异常类型:


namespace ExceptionStudy
{
sealed class MyException:Exception,ISerializable
{
//三个公有构造函数
public MyException()
: base() { }
public MyException(string message)
: base(message) { }
public MyException(string message, Exception innerException)
: base(message, innerException) { }
//私有字段
private string diskPath;
//只读属性
public string DiskPath
{
get { return this.diskPath; }
}
//重写公有属性Messgae
public override string Message
{
get
{
string msg = base.Message;
if (diskPath != null)
{
msg += Environment.NewLine + "Disk Path: " + diskPath;
}
return msg;
}
}
//因为定义了至少一个新的字段,所以要定义一个特殊的构造器用作反序列化。
private MyException(SerializationInfo info,
StreamingContext context)
:base(info,context)
{
//反序列化新定义的每个字段
diskPath = info.GetString("Diskpath");
}
#region ISerializable 成员
//因为定义了至少一个字段,所以要定义序列化方法
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("DiskPath", diskPath);
base.GetObjectData(info, context);
}
#endregion
public MyException(string message, string diskPath):this(message)
{
this.diskPath = diskPath;
}
public MyException(string message, string diskpath, Exception innerException)
: this(message, innerException)
{
this.diskPath = diskpath;
}
}
}
说实话,序列化这点没有搞明白,如果有谁看到,还望解答之