自定义异常的使用场景
看到一些文章说不要使用异常代替正常的控制流,对这个一直都不太清楚,随即查了下,做下笔记。
核心原则:区分预期错误(Expected Errors)
和意外异常(Unexpected Exceptions)
预期错误应当显示处理:输入验证、业务规则检查等都属于预期内的错误,应该通过返回值、状态码或结果对象明确传递。
假设需要验证用户输入内容合法性,有两种方式:
方式一:使用异常处理,不好的做法,会使调用方处理起来麻烦
// 通过抛出异常表示验证失败 public void ValidateEmail(string email) { if (!Regex.IsMatch(email, @"^[^@\s]+@[^@\s]+\.[^@\s]+$")) { throw new InvalidEmailException("邮箱格式错误"); } } // 调用方必须用 try-catch 处理正常逻辑 try { ValidateEmail("invalid-email"); Console.WriteLine("邮箱有效"); } catch (InvalidEmailException ex) { Console.WriteLine($"验证失败: {ex.Message}"); }
方式二:返回明确结果
// 返回一个结果对象,包含是否成功和错误信息 public ValidationResult ValidateEmail(string email) { bool isValid = Regex.IsMatch(email, @"^[^@\s]+@[^@\s]+\.[^@\s]+$"); return new ValidationResult { IsValid = isValid, ErrorMessage = isValid ? null : "邮箱格式错误" }; } // 调用方直接处理结果,无需 try-catch var result = ValidateEmail("invalid-email"); if (result.IsValid) { Console.WriteLine("邮箱有效"); } else { Console.WriteLine($"验证失败: {result.ErrorMessage}"); }
滥用异常的坏处
- 性能问题,异常处理成本高昂,CLR需要手机堆栈跟踪(Stack Trace)、展开调用栈,相比较条件判断,要慢数百倍。
- 代码可读性低,使用
try-catch
处理正常流程,会让其他人误以为是意外错误,而非预期业务逻辑分支。 - 破坏代码结构,正常的控制流被打断,其他人不得不处理异常,导致代码难以维护
所有业务流程中的错误都不属于异常吗?
非也,本质还是判断错误的性质:是预期内的业务规则失败,还是需要中断当前流程的严重错误。比如:
场景一:某些业务错误需要立即终止当前操作,且不适合通过返回值逐层传递,此时异常是更直接的选择。
场景二:需统一处理的特定错误类型
通过自定义异常,可在全局异常过滤器中统一处理特定业务错误,返回标准化响应。例如:
// 自定义异常 public class InsufficientBalanceException : Exception { public decimal RequiredAmount { get; } public InsufficientBalanceException(decimal required) : base($"余额不足,需支付 {required}") => RequiredAmount = required; } // 全局异常过滤器 public class BusinessExceptionFilter : IExceptionFilter { public void OnException(ExceptionContext context) { if (context.Exception is InsufficientBalanceException ex) { context.Result = new JsonResult(new { Code = 400, Message = ex.Message, RequiredAmount = ex.RequiredAmount }); context.ExceptionHandled = true; } } }
在判断是否使用自定义异常前,先问自己以下几个问题:
- 是否属于不可恢复的错误?
- 是否需要跨多层传递错误?
- 是否不属于预期内的业务规则失败?
- 是否需要强制调用方处理此错误?
- 发生频率是否很低?
若有半数以上结果为“是”,则说明适合自定义异常。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?