处理异常
目录
简介
处理 csharp 的异常最佳实践.
抛出异常
- 抛出
- 方法不能正常完成请求者的操作
- 无法继续执行
- 分类
- 非法参数: 超出范围的值
- 资源错误: 数据库、文件无法访问
- 逻辑错误: 商品库存不足
处理异常
不是所有异常拦截处理! 这样会导致难以排查错误
- 处理哪些异常
- 能恢复的异常. 超出范围的值, 可以提示用户
- 资源错误. 打开的文件, 链接数据库
- 可以封装异常, 比如
参数错误
. 可以在 catch 中返回页数不能是负数
- 处理事项
- 打印错误信息 + 堆栈
- 不要随意捕获所有的异常
Exception
- 使用
finally
或using
确保资源释放 - 避免嵌套
try-catch
,提高可读性
代码实践
设计 api
应该提供一些 api 让开发者正常写代码,而不是写满 try catch。
- file exists 就没有异常,而 file open 可能会有异常
- 也可以 try do work 返回 bool,但还是可能有必要异常
自定义异常
创建自定义异常应该至少有 3 个构造函数
public class InvalidDepartmentException : Exception
{
public InvalidDepartmentException() : base() { }
public InvalidDepartmentException(string message) : base(message) { }
public InvalidDepartmentException(string message, Exception inner) : base(message, inner) { }
}
抛出异常
- 业务异常
- 使用
throw new CustomException("123")
- 业务异常肯定会响应给用户, 所以会使用
ExceptionFilter
统一处理 - 非业务异常也会做拦截, 但会把异常信息变成日志, 对客户端省略
- 使用
- 不会响应给用户的异常
- 使用 guard
- 速度快, 会输出变量值, 代码更直观
- 可用于判断 null, 字符串检查, 集合检查, task 完成
- 没有 guard 就用 ThrowHelper
- 速度快, 代码更直观
- 使用 guard
处理异常
try{
file.open(@"1.txt");
}
catch (Exception e) when (e is ArgumentException || e is DivideByZeroException)
{
log.warning("aaa",e);
}
finally{
file?.close();
}
全局异常
c# - .NET Global exception handler in console application - Stack Overflow
using System;
class Program {
static void Main(string[] args) {
System.AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
throw new Exception("Kaboom");
}
static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e) {
Console.WriteLine(e.ExceptionObject.ToString());
Console.WriteLine("Press Enter to continue");
Console.ReadLine();
Environment.Exit(1);
}
}