C# 所有 .NET 异常都可序列化吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/342528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Are all .NET exceptions serializable?
提问by Esteban Araya
Can all .NET exception objects be serialized?
所有 .NET 异常对象都可以序列化吗?
采纳答案by JaredPar
Yes and no. As Jeff and others have pointed out, the all exception classes should and almost always are serializable. If you run across a particular exception class that is not serializable, it is quite possibly a bug.
是和否。正如 Jeff 和其他人指出的那样,所有异常类都应该并且几乎总是可序列化的。如果遇到不可序列化的特定异常类,则很可能是一个错误。
But when considering serializability you need to consider both the immediate class and all types which are members of this type (this is a recursive process). The base Exception class has a Dataproperty which is of type IDictionary. This is problematic because it allows you, or anyone else, to add any object into the Exception. If this object is not serializable then serialization of the Exception will fail.
但是在考虑可序列化性时,您需要同时考虑直接类和属于该类型的所有类型(这是一个递归过程)。Exception 基类有一个IDictionary 类型的Data属性。这是有问题的,因为它允许您或其他任何人将任何对象添加到异常中。如果此对象不可序列化,则异常的序列化将失败。
The default implementation of the Data property does do some basic checking to ensure an object being added is serializable. But it is flawed in several ways
Data 属性的默认实现会做一些基本检查,以确保添加的对象是可序列化的。但它在几个方面存在缺陷
- Only does top level checking for serializability of a type and this check is only done by checking Type.IsSerializable (not a 100% solid check).
- The property is virtual. A derived exception type could override and use a Hashtable which does 0 checking.
- 仅对类型的可序列化性进行顶级检查,并且此检查仅通过检查 Type.IsSerializable(不是 100% 可靠检查)来完成。
- 财产是虚拟的。派生的异常类型可以覆盖并使用执行 0 检查的 Hashtable。
回答by Matt Briggs
System.Exception
implements ISerializable
and it is the base class for all exceptions, so yes.
System.Exception
实现ISerializable
并且它是所有异常的基类,所以是的。
See: http://msdn.microsoft.com/en-us/library/system.exception.aspx
请参阅:http: //msdn.microsoft.com/en-us/library/system.exception.aspx
回答by Jeff Atwood
Yes, but historically there have been (no pun intended) exceptions.
是的,但从历史上看,有(没有双关语意)例外。
In other words, all Exceptions SHOULD be serializable, but some custom Exceptions from third party code may notbe, depending on how they're implemented.
换句话说,所有异常都应该是可序列化的,但是来自第三方代码的一些自定义异常可能不是,这取决于它们是如何实现的。
For example, in the .NET 1.0 era, exceptions from the official Microsoft Oracle database provider were not serializable, due to bugs in their code.
例如,在 .NET 1.0 时代,由于其代码中的错误,来自官方 Microsoft Oracle 数据库提供程序的异常不可序列化。
回答by Barry Kelly
System.Exception
implements ISerializable
, but descendants might not deserialize if they don't implement the correct overloaded constructor with signature (SerializationInfo,StreamingContext)
.
System.Exception
实现ISerializable
,但如果后代没有使用签名实现正确的重载构造函数,则它们可能不会反序列化(SerializationInfo,StreamingContext)
。
回答by drwatsoncode
This question has already been answered sufficiently, but for programmers who are new to C# or to Serialization, I think it is actually very helpful to point out that in general, Exceptions are NOTserializable!
这个问题已经得到了充分的回答,但是对于刚接触 C# 或序列化的程序员来说,我认为指出通常情况下异常是不可序列化的实际上非常有帮助!
That might sound a bit provocative, but let me explain.
这听起来可能有点挑衅,但让我解释一下。
It's true that all Exceptions implement the ISerializable interface, but this is only suggests that it shouldbe serializable. But implementing the interface does NOT make an object Serializable (which in this context implies that the Exception can be both serialized anddeserialized).
确实所有异常都实现了 ISerializable 接口,但这只是表明它应该是可序列化的。但是实现接口不会使对象可序列化(在这种情况下,这意味着异常可以被序列化和反序列化)。
The most accurate answer to this question, as others have pointed out, is that many but certainly not all exceptions in the .Net Frameworkare Serializable. But if the question is using the term ".Net Exception" in a broader scope, e.g. an Exception derivedfrom System.Exception, then the better and more helpful answer, in terms of best practices and avoiding bugs, is the assertion I made above, that in general Exceptions are not Serializable.
正如其他人所指出的,对这个问题最准确的答案是.Net 框架中的许多但肯定不是所有的异常都是可序列化的。但是,如果问题是在更广泛的范围内使用术语“.Net Exception”,例如从 System.Exception派生的异常,那么就最佳实践和避免错误而言,更好、更有用的答案是我在上面所做的断言,一般来说异常是不可序列化的。
Here's why:
As stated previously, for an Exception to be truly Serializable, it must have the proper constructor ctor(SerializationInfo, StreamingContext)
and it must be decorated with the proper attribute. Importantly, neither of these constraints cause compiler errors if they are omitted!
原因如下:如前所述,对于真正可序列化的异常,它必须具有正确的构造函数ctor(SerializationInfo, StreamingContext)
并且必须用正确的属性进行修饰。重要的是,如果省略这些约束,它们都不会导致编译器错误!
What this means is that NOclass derived from Exception is Serializable unless these extra, optional (from the compiler's perspective) steps are taken.
这是什么意思是,NO类从Exception派生了Serializable接口,除非这些额外的,可选的(从编译器的角度来看)采取措施。
I.e. any unseasoned/unaware coder who derives a new Exception like below has just created an exception that is NOT Serializable.
即任何没有经验的/不知道的编码器派生如下新的异常刚刚创建了一个不可序列化的异常。
class MyNewException : Exception { }
Visual studio has a great "Exception" snippet that lets you generate new serializable exceptions pretty quickly. But even in this case, there is nothing to remind or help the programmer to actually Serialize object properties. For example, even if the class below had the appropriate constructor and attribute, the MyNewField
property would not be serialized without additional code in both the constructor and in GetObjectData.
Visual Studio 有一个很棒的“异常”片段,可以让您非常快速地生成新的可序列化异常。但即使在这种情况下,也没有什么可以提醒或帮助程序员实际序列化对象属性的。例如,即使下面的类具有适当的构造函数和属性,MyNewField
如果在构造函数和 GetObjectData 中没有额外的代码,属性也不会被序列化。
class MyNewException : Exception
{
public MyNewField { get; set; }
}
So, the major point here is that if you must rely on proper Exception serialization & deserialization for some reason, should be completely aware that when it comes to any custom code or assemblies, there is no guarantee that it will work. Also, since the required constructor is usually protected, you will not necessarily be able to easily verify that it is present (without reflection).
所以,这里的重点是,如果您出于某种原因必须依赖正确的异常序列化和反序列化,应该完全意识到,当涉及到任何自定义代码或程序集时,不能保证它会起作用。此外,由于所需的构造函数通常是受保护的,因此您不一定能够轻松验证它是否存在(无需反射)。
In my own projects I have at some points created exception "Proxies" that can store some of the information (e.g. Message etc) from Exceptions that are not serializable themselves. These can be used to serialize some of the information, or alternatively to deserialize data written by an Exception that doesn't have the appropriate constructor.
在我自己的项目中,我在某些时候创建了异常“代理”,它可以存储来自自身不可序列化的异常的一些信息(例如消息等)。这些可用于序列化某些信息,或者反序列化由没有适当构造函数的异常写入的数据。