关于C#:C# – 为什么要实现标准的异常构造函数?

C# - Why implement standard exception constructors?

来自msdn,代码分析警告CA1032:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Exception types must implement the following constructors:
<ul>


<li>
public NewException()

<li>
public NewException(string)

<li>
public NewException(string, Exception)

<li>
protected or private NewException(SerializationInfo, StreamingContext)
</ul>

。我理解序列化构造函数背后的目的,但是"需要"其他构造函数背后的理由是什么?为什么我不应该定义任何对我的异常的使用有意义的构造函数呢?如果我不想在不传递消息的情况下抛出MyException,那该怎么办?为什么我应该定义一个无参数的构造函数?如果我希望MyException有一个int属性,而我只希望初始化该属性的构造函数怎么办?


你得到了一些很好的答案。我只是想补充一点,提供这些额外的构造函数并不一定需要很多编码。因为它们已经在基类中实现了,所以您可以简单地让它完成工作:

1
2
3
4
5
6
7
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...
}

因此,您只需要在异常的行为与基类的行为不同的地方实现代码。


这是警告,不是要求。这基本上是最不令人惊讶的原则。提供全部4个选项,使习惯于"常规"C例外的人更容易使用您的C例外。如果您有充分的理由忽略指导原则,那么就这样做。但它将打破某些使用场景,并使类的直观性有所下降。


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

如果没有反序列化构造函数和[serializable]属性,异常将无法在分布式环境中运行,并可能导致其他问题。鉴于这一点,以及熟悉C开发人员的方面,最好实现至少4个标准异常构造函数,并用[可序列化]标记异常。


无参数和序列化构造函数由通用"异常路由"代码使用,这些代码需要在域之间(例如,在服务和客户机之间的Internet上)移动异常。

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

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


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