C# - 为什么要实现标准的异常构造函数?

Ale*_*xis 34 c# coding-style exception

从MSDN,代码分析警告CA1032:

Exception types must implement the following constructors: 
  • public NewException()
  • public NewException(string)
  • public NewException(string, Exception)
  • protected or private NewException(SerializationInfo, StreamingContext)
我理解序列化构造函数背后的目的,但是"要求"其他构造函数背后的理由是什么?为什么我不应该只定义对我的异常使用有意义的构造函数?如果我不想在不传递消息的情况下抛出MyException,我该怎么定义无参数构造函数呢?如果我希望MyException具有int属性并且我只想要初始化该属性的构造函数,该怎么办?

Mat*_*hen 11

这是一个警告,而不是一个要求.这基本上是最不惊讶原则.提供所有4个使得习惯于"常规"C#例外的人更容易使用你的.如果您有充分理由忽略该指南,请执行此操作.但它会破坏某些使用场景,并使你的课程不那么直观.

  • 它不仅会使它不那么直观 - 它将特别禁用它,无论是在异常远程处理方案中还是在调用者需要将其用作另一个异常的包装时. (3认同)

Fre*_*örk 11

你已经得到了一些好的答案.我只想补充说,提供这些额外的构造函数并不一定需要大量的编码.由于它们已经在基类中实现,因此您可以简单地让它们完成工作:

public class MyCustomException : Exception
{
    public MyCustomException() : base() { }
    public MyCustomException(string message) : base(message) { }
    public MyCustomException(string message, Exception innerException) : base(message, innerException) { }
    // and so on...
}
Run Code Online (Sandbox Code Playgroud)

因此,您只需要实现代码,其中异常的行为与基类的行为不同.

  • 这怎么可能是最佳答案?它甚至都没有试图回答问题的“为什么”部分。使用建议的方法,代码库将充满样板代码,在我看来,这些样板代码不提供任何实际的业务价值,并且会增加复杂性。 (3认同)

Dan*_*ker 7

无参数和序列化构造函数由需要在域之间移动异常的通用“异常路由”代码使用(例如,跨服务和客户端之间的互联网)。

采用另一个的Exception方法是可以通过InnerException属性链接所有异常。

最后,还有一个接受消息字符串的方法,它有助于合理一致地使用异常。


jri*_*sta 5

实现标准异常构造函数允许人们以内置于所有现有 .NET 异常中的标准、熟悉的方式使用异常。前三个可以是可选的,如果由于某种原因您不想使用其中一个(尽管我无法理解为什么您会想要使用它们。)但是,最后一个是反序列化构造函数,如果您愿意如果您的例外是在任何类型的分布式环境(.NET Remoting、ASP.NET Web Services、WCF 等)中得到支持,那么它就非常重要。

如果没有反序列化构造函数和 [Serialized] 属性,您的异常将无法在分布式环境中运行,并且可能会导致其他问题。鉴于此,以及精通 C# 开发人员的熟悉程度,最好至少实现 4 个标准异常构造函数,并使用 [Serialized] 标记异常。


mqp*_*mqp -1

好吧,为了使自定义异常正确可用,接受内部异常的构造函数是非常必要的。如果没有它,如果有人捕获了您的异常,他们将无法触发更具描述性或适当的异常,同时保留您的原始异常(及其携带的信息,例如堆栈跟踪)。

  • 我认为你有这个倒退 - 接受内部异常的那个是这样,如果你的代码捕获另一个异常,你可以将你的异常包装在它周围 (8认同)