2

什么是使异常可序列化的正确方法的答案?表示自定义异常的“正确”基本实现包括 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,它本身进行自定义序列化。我可以理解。但是我必须实现其他 ctors才能正确提供可序列化的异常吗?我知道,如果我想允许一个类型可 xml 序列化,我需要提供默认(无操作)ctor。[Serializable] 也一样吗?暂时,让我们将自己局限在 [Serializable] 的狭隘关注上,而将任何关于“框架设计”的更广泛的指导原则放在一边。

  2. 转向更广泛的问题:指南说定义例外应该实现 4 个常见的 ctors。该指南背后的原因是什么?如果我设计了一个自定义异常,如果我不提供 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 博客:使异常可序列化

4

4 回答 4

2

相关的代码分析警告是 CA1032,参考页面提供了这个理由:

未能提供完整的构造函数集会使正确处理异常变得困难。例如,带有签名 NewException(string, Exception) 的构造函数用于创建由其他异常引起的异常。如果没有此构造函数,您将无法创建和抛出包含内部(嵌套)异常的自定义异常的实例,这是托管代码在这种情况下应该执行的操作。按照惯例,前三个异常构造函数是公共的。第四个构造函数在非密封类中是受保护的,在密封类中是私有的。

只有您或您的项目团队可以决定您的情况是否需要例外(对不起...)

于 2009-07-01T12:24:56.930 回答
1

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

exception

在编辑器中并按 Tab(两次?)。这将创建它们,让您有机会为该类指定一个新名称。

于 2009-07-01T12:27:07.910 回答
1

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

于 2009-07-08T03:20:33.797 回答
0

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

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

于 2009-07-01T12:21:57.967 回答