【问题标题】:re: design of custom exceptions: must I implement the default constructor? the "inner exception" constructor?回复:自定义异常的设计:我必须实现默认构造函数吗? “内部异常”构造函数?
【发布时间】:2010-11-07 06:35:33
【问题描述】:

What is the correct way to make exceptions serializable? 的答案说自定义异常的“正确”基本实现包括 4 个 ctor:

[Serializable]
public class SerializableExceptionWithoutCustomProperties : Exception
{
    public SerializableExceptionWithoutCustomProperties()
    {
    }

    public SerializableExceptionWithoutCustomProperties(string message) 
        : base(message)
    {
    }

    public SerializableExceptionWithoutCustomProperties(string message, Exception innerException) 
        : base(message, innerException)
    {
    }

    // Without this constructor, deserialization will fail
    protected SerializableExceptionWithoutCustomProperties(SerializationInfo info, StreamingContext context) 
        : base(info, context)
    {
    }
}

马上,我会说这对于 Exception 类型来说是一个非常糟糕的名字。但是,除此之外,

  1. 为了二进制序列化,这就是 SO 问题所指的,我必须实现所有 4 个构造函数吗?我认为出于 [Serializable] 的目的,我必须提供一个接受 2 个类型参数(SerializationInfo、StreamingContext)的 ctor,因为异常源自 System.Exception,它本身进行自定义序列化。我可以理解。但是我必须实现其他 ctor,以便正确提供可序列化的异常吗?我知道,如果我想允许一个类型可 xml 序列化,我需要提供默认(无操作)ctor。 [Serializable] 也一样吗?暂时,让我们将自己局限在 [Serializable] 的狭隘关注点上,而将有关“框架设计”的任何更广泛的准则放在一边。

  2. 转向更广泛的问题:The guidelines say自定义异常应该实现 4 个公共 ctor。该指南背后的原因是什么?如果我设计了一个自定义异常,如果我不提供 null/default ctor,这真的是不礼貌,甚至是错误吗?如果我不提供允许 innerException 的 ctor,这真的是不礼貌,甚至是错误吗?为什么?考虑一下我的自定义异常是在我的库代码中生成的,我曾经抛出的唯一实例包括一条消息,而没有 innerException。

  3. 简而言之,对于不提供其他属性的自定义异常,以下代码是否可以接受?


[Serializable]
public class CustomException : Exception
{
    public CustomException(string message) : base(message) { }

    // Without this constructor, deserialization will fail
    protected CustomException(SerializationInfo info, StreamingContext context) 
        : base(info, context) { }
}

另请参阅:Winterdom blog: Make exceptions Serializable

【问题讨论】:

  • 我第一次看到有人使用“ctor”来表示构造函数 O_o。对我来说幸运的是,您确实使用了完整的单词一次,所以我可以理解标题。我建议你改变你的标题...

标签: .net exception class-design serializable


【解决方案1】:

相关的代码分析警告是 CA1032,reference page 提供了这个理由:

未能提供全套 构造函数可能难以 正确处理异常。为了 例如,构造函数 签名NewException(字符串, 异常)用于创建 由其他原因引起的异常 例外。没有这个构造函数, 你不能创建和抛出一个 您的自定义异常的实例 包含一个内部(嵌套)异常, 这是托管代码应该做的 在这样的情况下。前三个 异常构造函数是公共的 习俗。第四个构造函数是 在非密封类中受到保护,并且 密封类中的私有。

只有您或您的项目团队才能决定您的情况是否需要例外(抱歉...)

【讨论】:

  • 啊,很聪明。感谢您的摘录。这很有帮助。
【解决方案2】:

嘿,我知道这至少是 Microsoft 建议的。如果您使用 VS2008(或者更早的版本),您可以轻松地让 Visual Studio 为您创建它们,只需键入

exception

在编辑器中并按 Tab(两次?)。这将创建它们,让您有机会为类命名。

【讨论】:

    【解决方案3】:

    我不喜欢任何答案。我正在解决我提出的解决方案,即..我可以消除自定义异常中的“正常”构造函数,包括默认构造函数和嵌套构造函数。此外,由于跨应用程序域调用,我需要确保序列化有效。

    【讨论】:

      【解决方案4】:

      建议:如果其他人将使用您的异常,并且由于这些其他人熟悉 .NET 异常,那么为什么不按照指南进行操作呢?它们与 .NET Framework 使用的相同。

      考虑到您要定义的自定义异常类型的数量,您是否觉得工作量太大?如果是这样,那么这将是遵循准则的另一个原因,该准则指定您不应创建大量自定义异常。

      【讨论】:

      • 不,没有太多工作 - 构造函数已经在我的代码中。但是,我的代码没有使用其中的一半,我想考虑将它们作为代码清理的一部分删除。这些例外不打算在我提供的库之外使用。它们是由库抛出的,但我不希望任何其他代码抛出它们。我应该允许那个,支持那个是典型的吗?
      • 如果它们都用于您的库,请将它们设为内部类。您仍然应该实现所有这些构造函数等 - 您或以后的维护者会期望它们“就像 .NET 中的所有其他异常一样”。
      • 我想知道,在自定义异常包含捕获异常发生时发生的一些事情的额外属性的情况下,我们如何强制引发异常的代码如果我们提供不需要的构造函数,包括这些细节?
      • 没有。始终包含内部异常构造函数,并始终酌情使用它。它提供了异常的完整历史记录。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-28
      • 1970-01-01
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多