处理异常

处理 csharp 的异常最佳实践.

  • 抛出
    • 方法不能正常完成请求者的操作
    • 无法继续执行
  • 分类
    • 非法参数: 超出范围的值
    • 资源错误: 数据库、文件无法访问
    • 逻辑错误: 商品库存不足

不是所有异常拦截处理! 这样会导致难以排查错误

  • 处理哪些异常
    • 能恢复的异常. 超出范围的值, 可以提示用户
    • 资源错误. 打开的文件, 链接数据库
    • 可以封装异常, 比如 参数错误. 可以在 catch 中返回 页数不能是负数
  • 处理事项
    • 打印错误信息 + 堆栈
    • 不要随意捕获所有的异常 Exception
    • 使用 finallyusing 确保资源释放
    • 避免嵌套 try-catch,提高可读性

应该提供一些 api 让开发者正常写代码,而不是写满 try catch。

  • file exists 就没有异常,而 file open 可能会有异常
  • 也可以 try do work 返回 bool,但还是可能有必要异常

创建自定义异常应该至少有 3 个构造函数

csharp

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
      • 速度快, 代码更直观

csharp

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

csharp

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