Seb*_*ull 2 c# inheritance exception
Exception在C#中创建自定义类型时,为什么重载所有这些构造函数被认为是一种好习惯:
Exception()
Exception(String)
Exception(String, Exception)
Run Code Online (Sandbox Code Playgroud)
请参阅: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;
}
}
Run Code Online (Sandbox Code Playgroud)
免责声明:我知道我可以传递其他信息,所以这只是一个相当简单的例子.
更新1:
据我理解,我将覆盖所有构造函数,但也添加了Exception所需的所有参数.那是对的吗?
例:
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)
Run Code Online (Sandbox Code Playgroud)
因为这两个Message和InnerException属性都是在Exception课堂上只读.这意味着设置它们的唯一方法是通过构造函数.您的实现不允许设置这些属性,因为您省略了相关的构造函数.这意味着你的例外:
丢失导致它的另一个例外中包含的有价值的信息(如果有的话).它的InnerException始终为null.
记录或显示给用户时不显示人类可读信息.记录异常时 - 仅考虑基Exception类的属性,例如Message和InnerException.这些属性始终是空为你例外,所以只有堆栈跟踪(甚至未完成)将出现在日志(你的FailedSystem和OperationName不会出现有太多).
您可能认为代码的用户将捕获特定的ExternalSystemCallException异常,然后根据其属性执行操作,但这不是经常发生的事情.您的代码可能会被用作较大操作的一部分,然后堆栈中会有一些catch-all处理程序,它只会记录异常并向用户显示一些错误消息.因此将基本Exception属性设置为有意义的值是不明智的.
要"修复"您的异常类型,您可以考虑执行以下操作:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
这样,您始终设置Message为有意义的值,并允许InnerException在需要时传递.Exception如果在不提供系统和操作名称值的情况下抛出类型异常,则可以省略空构造函数.