所有.NET例外都是可序列化的吗?

时间:2008-12-05 00:28:28

标签: c# .net exception

是否可以序列化所有.NET异常对象?

5 个答案:

答案 0 :(得分:38)

是和否。正如杰夫和其他人所指出的那样,所有异常类应该并且几乎总是可序列化的。如果您遇到不可序列化的特定异常类,则很可能是一个错误。

但是在考虑可序列化时,您需要考虑直接类和所有类型成员的类型(这是一个递归过程)。基本Exception类具有Data属性,其类型为IDictionary。这是有问题的,因为它允许您或任何其他人将任何对象添加到异常中。如果此对象不可序列化,则异常的序列化将失败。

Data属性的默认实现会进行一些基本检查,以确保添加的对象是可序列化的。但它在几个方面存在缺陷

  • 仅对顶级检查类型的可序列化,此检查仅通过检查Type.IsSerializable(不是100%实体检查)来完成。
  • 该属性是虚拟的。派生的异常类型可以覆盖并使用执行0检查的Hashtable。

答案 1 :(得分:15)

是的,但历史上曾有(没有双关语)例外。

换句话说,所有异常应该是可序列化的,但是第三方代码中的某些自定义异常可能,具体取决于它们的实现方式。

例如,在.NET 1.0时代,由于代码中的错误,官方Microsoft Oracle数据库提供程序的异常不可序列化。

答案 2 :(得分:10)

这个问题已经得到了充分的回答,但是对于不熟悉C#或序列化的程序员来说,我认为实际上非常有帮助的是,通常情况下,异常可序列化! / p>

这可能听起来有点挑衅,但让我解释一下。

所有Exceptions都实现了ISerializable接口,但这仅表明它可序列化。但是实现接口不会使对象Serializable(在此上下文中暗示Exception可以序列化反序列化)。

正如其他人所指出的,对这个问题的最准确答案是, .Net Framework 中的许多例外但并非所有例外都是可序列化的。但是,如果问题是在更广泛的范围内使用术语“.Net Exception”,例如来自System.Exception的异常派生,然后就最佳实践和避免错误而言,更好,更有帮助的答案是我在上面做出的断言,一般情况下,异常不是可序列化的。

原因如下: 如前所述,要使Exception成为真正的Serializable,它必须具有正确的构造函数ctor(SerializationInfo, StreamingContext),并且必须使用适当的属性进行修饰。重要的是,如果省略这些约束,这些约束都不会导致编译器错误!

这意味着从Exception派生的 NO 类是Serializable,除非采取这些额外的,可选的(从编译器的角度来看)步骤。

即。任何未经干扰/不知情的编码器派生出一个像下面这样的新例外,它刚刚创建了一个非Serializable的例外。

class MyNewException : Exception { }

Visual Studio有一个很棒的“异常”代码段,可让您快速生成新的可序列化异常。但即使在这种情况下,也没有什么可以提醒或帮助程序员实际序列化对象属性。例如,即使下面的类具有适当的构造函数和属性,如果构造函数和GetObjectData中没有其他代码,MyNewField属性也不会被序列化。

class MyNewException : Exception 
{
    public MyNewField { get; set; }
}

所以,这里的主要观点是,如果你必须依赖正确的异常序列化和反序列化由于某种原因,应该完全清楚,当涉及任何自定义代码或程序集时,不能保证它将起作用。此外,由于所需的构造函数通常受到保护,因此您不一定能够轻松验证它是否存在(没有反射)。

在我自己的项目中,我在某些方面创建了异常“代理”,它可以存储来自异常的一些信息(例如消息等),这些异常本身不可序列化。这些可用于序列化某些信息,或者反序列化由没有相应构造函数的Exception写入的数据。

答案 3 :(得分:6)

System.Exception实现ISerializable,但如果后代没有使用签名(SerializationInfo,StreamingContext)实现正确的重载构造函数,则后代可能不会反序列化。

答案 4 :(得分:2)

System.Exception实现ISerializable,它是所有异常的基类,所以是的。

请参阅:http://msdn.microsoft.com/en-us/library/system.exception.aspx