C# 6.0本质论(异常)

十、异常

10.1 异常条件

  • when子句
    • 捕获异常时可以加条件判断是否进行处理
      • 例如,catch( ArgumentNullException e) when (tag==true){ . . . }

10.2 重新引发已存在的异常

  • 在catch块中调用空throw
    • 将捕获的异常再次抛出而不替换栈信息
    • 只能在catch块中调用

10.3 引发现有异常而不替换栈信息

  • 有些异常在捕获之前已经经过包装
  • System.Runtime.ExceptionServices.ExceptionDispatchInfo
    • 提取包装后的异常中的内部异常
Task task = writeWebRequestSizeAsync(url);
try
{
	while(!task.Wait(100)){
		Console.write(".");
	}
}
catch(AggregateException exception)
{
	exception = exception.Flattern();
	ExceptionDispatchInfo.Capture(exception.innerException).Throw();
}

10.4 常规catch块

  • catch{ } 是catch(Exception exception){ }的简写,用于捕获之前未被捕获的异常
    • 其他语言的异常不一定都派生自Exception
    • 在C# 2.0 之后,所有进入程序集的异常,都会被包装成从Exception派生
    • 缺点是没有一个可访问的异常实例

10.5 异常处理规范

  • 在大多数情况下,catch块应放在调用栈中较高的位置
    • 较低位置可能被重复调用,同一个异常问题被重复多次记录
  • 尽量少使用Exception或常规catch块
    • 有部分异常是无法通过代码处理从异常恢复
      • 例如,OutOfMemoryException,只能通过关闭应用程序解决

10.6 自定义异常

  • 必须从Exception或其子类中派生
  • 可用innerException属性保存原始异常
  • 构造器应包括无参构造、string参数构造以及string+内部异常的构造
class DatabaseException : System.Exceptio
{
	public DatabaseException()
	{
		//...
	}
	public DatabaseException(string message)
	{
		InnerException = exception;
	}
	public DatabaseException(string message, System.Data.SqlClient.SQLException exception)
	{
		InnerException = exception;
	}
}

10.7 可序列化异常

  • 可序列化对象
    • 可以持久化为一个流,然后根据这个流来重新实例化的对象
  • 方式
    • 使用System.SerializableAttribute
      • 异常类前加 [Serializable]
    • 或者实现ISerizable接口
    • 必须包含一个构造器来获取System.Runtime.Serialization.SerializationInfo和System.Runtime.Serialization.StreamingContext

10.8 封装异常并重新引发

  • 栈中较低位置引发的异常在较高处捕获到时已经没有意义时,可考虑重新引发一个不同的异常
    • 例如,地理坐标请求API引发UnauthorizedAccessException,和调用的API完全无关的异常,给调用者造成困惑而不是帮助
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值