现代 C# 开发:简化自定义异常
发布: (2025年12月21日 GMT+8 05:00)
3 min read
原文: Dev.to
Source: Dev.to
Introduction
错误是不可避免的。有时它们很简单,有时又非常特定于你的业务领域。C# 提供了许多内置异常,但它们并不总能完整地说明问题。自定义异常可以让你清晰地传达领域特定的问题。
When to Use a Custom Exception
考虑一个订单系统,用户尝试下单却违反了业务规则。
throw new InvalidOperationException("User cannot place this order");
内置异常可以工作,但信息过于通用。自定义异常则提供了更多上下文:
throw new OrderNotAllowedException(userId);
Defining a Basic Custom Exception
自定义异常只是继承自 Exception 的类。
public class OrderNotAllowedException : Exception
{
public OrderNotAllowedException(string message)
: base(message)
{
}
}
这个最小版本已经足以开始使用。
Adding Contextual Information
与其把所有信息都塞进消息字符串,不如将相关数据暴露为属性。
public class OrderNotAllowedException : Exception
{
public Guid UserId { get; }
public OrderNotAllowedException(Guid userId)
: base($"User {userId} is not allowed to place an order")
{
UserId = userId;
}
}
现在日志和错误处理程序可以直接访问 UserId,无需解析字符串,从而简化调试。
.NET Version Considerations
在较旧的 .NET 版本(例如 .NET Framework 4.x 及更早)中,通常需要为序列化添加额外的构造函数。使用现代 .NET(Core、5+、6+、7+)时,上面展示的简单类已经足够。
Avoid Overusing Custom Exceptions
自定义异常很有用,但也可能被滥用。请尽量避免:
- 将异常用于普通的控制流
- 创建非常通用且没有实际价值的自定义异常
- 在公共 API 中暴露内部异常细节
如果内置异常已经能够很好地描述问题,优先使用它。
Guideline Checklist Before Creating a Custom Exception
- 这是否代表一个真正的异常情况?
- 它是否比简单的消息字符串提供了更多意义?
- 名称是否能清晰描述问题?
如果以上三个问题的答案都是 是,那么自定义异常是合适的选择。
Conclusion
自定义异常是一个小功能,却能让你的代码更加清晰、易于维护。恰当地使用它们,可以简洁地说明出错的原因和具体情形。