异常构造函数重载

时间:2018-02-15 13:34:25

标签: c# inheritance exception

在C#中创建自定义Exception类型时,为什么认为重载所有这些构造函数是一种好习惯:

Exception()
Exception(String)
Exception(String, Exception)

请参阅: https://docs.microsoft.com/en-us/dotnet/standard/exceptions/best-practices-for-exceptions#include-three-constructors-in-custom-exception-classes

在任何这些建议中,我都没有找到理由。

如果我想创建一个自定义Exception,如果在调用另一个系统时发生未知错误,则会抛出该自定义public class ExternalSystemCallException : Exception { public string FailedSystem { get; } public string OperationName { get; } public ExternalSystemCallFailedException(string failedSystem, string operationName) { FailedSystem = failedSystem; OperationName = operationName; } } ,为什么在此处覆盖其他构造函数被认为是好的,如果我只需要有关失败的信息系统及其导致的操作:

Exception(string failedSystem, string operationName) 
    : base()

Exception(string failedSystem, string operationName, string message) 
    : base(message)

Exception(string failedSystem, string operationName, string message, Exception innerException) 
    : base(message, innerException)

免责声明:我知道我可以传递其他信息,所以这只是一个相当简单的例子。

更新1:

据我了解,我将覆盖所有构造函数,但也添加了Exception所需的所有参数。这是对的吗?

示例:

{
    path: 'categories/:id', children: [
    {path: '**', component: SubcategoriesListComponent}
]
}

1 个答案:

答案 0 :(得分:5)

因为Message类上的InnerExceptionException属性都是只读的。这意味着设置它们的唯一方法是通过构造函数。您的实现不允许设置这些属性,因为您省略了相关的构造函数。这意味着你的例外:

  1. 丢失导致它的另一个例外中包含的有价值的信息(如果有的话)。它的InnerException始终为null。

  2. 记录或显示给用户时,不显示任何人类可读信息。记录异常时 - 仅考虑基本Exception类的属性,例如MessageInnerException。对于您的异常,这些属性始终为null,因此只有堆栈跟踪(甚至不完整)将显示在日志中(您的FailedSystemOperationName也不会出现在那里)。

    < / LI>

    您可能认为代码的用户会捕获特定的ExternalSystemCallException异常,然后根据其属性执行操作,但这不是经常发生的情况。您的代码可能会被用作较大操作的一部分,然后堆栈中会有一些catch-all处理程序,它只会记录异常并向用户显示一些错误消息。因此,将基础Exception属性设置为有意义的值是不可取的。

    To&#34; fix&#34;您可能会考虑做以下事情的异常类型:

    public class ExternalSystemCallException : Exception
    {
        public string FailedSystem { get; }
        public string OperationName { get; }
    
        public ExternalSystemCallException(
                 string failedSystem, 
                 string operationName, 
                 Exception innerException = null)
                : base($"Operation {operationName} failed in {failedSystem}", innerException) {
            FailedSystem = failedSystem;
            OperationName = operationName;
        }        
    }
    

    这样,您始终将Message设置为有意义的值,并允许在需要时传递InnerException。如果在没有提供系统和操作名称值的情况下抛出类型异常,那么可以省略空Exception构造函数。