C#自定义Exception:重写的Message属性与构造函数执行顺序?
问题解答
1. 构造函数与重写Message属性的有效性
你第一种写法里重写Message属性的方式是完全有效的,能达到你想要的效果:无论实例化异常时构造函数传入什么message参数,外部访问该异常的Message属性时,都会得到你定义的固定值"Email or password is incorrect"。构造函数的调用逻辑不会影响你对Message属性的重写——这是子类对基类属性的多态覆盖,只要属性被访问,就会执行子类的重写逻辑。
2. 执行顺序说明
构造函数和重写的Message属性不是同一阶段执行的:
- 构造函数在实例化异常对象时立即执行:先调用基类
Exception的构造逻辑,再执行子类UserNotFoundException的构造代码,整个过程属于对象初始化阶段; - 重写的
Message属性是延迟执行的:它只有在被外部代码主动访问(比如var ex = new UserNotFoundException(); Console.WriteLine(ex.Message);)的时候才会被求值,不会在构造阶段运行。
3. 避免代码重复的优化写法
针对你第二种写法的重复问题,可以通过构造函数链+常量定义来消除重复,同时保持逻辑清晰:
public class UserNotFoundException : Exception { // 把默认消息定义为常量,统一维护 private const string DefaultErrorMessage = "Email or password is incorrect"; public UserNotFoundException() : this(DefaultErrorMessage) { } public UserNotFoundException(string? message) : this(message, null) { } public UserNotFoundException(string? message, Exception? innerException) : base(message ?? DefaultErrorMessage, innerException) { } }
这种写法的好处是:
- 默认消息只定义一次,避免重复硬编码;
- 通过构造函数链复用逻辑,所有构造最终都调用最底层带完整参数的构造函数;
- 支持自定义消息(如果需要的话),同时在传入
null时自动使用默认消息。
如果你确实需要强制固定Message值,不允许自定义,那第一种重写Message的写法更直接,但要注意:Exception基类的ToString()方法会用到Message属性,这时候也会调用你的重写逻辑,符合预期。
内容的提问来源于stack exchange,提问作者O S
相关产品推荐
相关产品推荐

