在C#中创建自定义Exception
类型时,为什么认为重载所有这些构造函数是一种好习惯:
Exception()
Exception(String)
Exception(String, Exception)
在任何这些建议中,我都没有找到理由。
如果我想创建一个自定义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}
]
}
答案 0 :(得分:5)
因为Message
类上的InnerException
和Exception
属性都是只读的。这意味着设置它们的唯一方法是通过构造函数。您的实现不允许设置这些属性,因为您省略了相关的构造函数。这意味着你的例外:
丢失导致它的另一个例外中包含的有价值的信息(如果有的话)。它的InnerException始终为null。
记录或显示给用户时,不显示任何人类可读信息。记录异常时 - 仅考虑基本Exception
类的属性,例如Message
和InnerException
。对于您的异常,这些属性始终为null,因此只有堆栈跟踪(甚至不完整)将显示在日志中(您的FailedSystem
和OperationName
也不会出现在那里)。
您可能认为代码的用户会捕获特定的ExternalSystemCallException
异常,然后根据其属性执行操作,但这不是经常发生的情况。您的代码可能会被用作较大操作的一部分,然后堆栈中会有一些catch-all处理程序,它只会记录异常并向用户显示一些错误消息。因此,将基础Exception
属性设置为有意义的值是不可取的。
To" fix"您可能会考虑做以下事情的异常类型:
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
构造函数。