为什么类在.Net中默认不可序列化?

为什么类在.Net中默认不可序列化?,.net,serialization,types,.net,Serialization,Types,开发人员必须通过显式使用SerializableAttribute来“选择”使类可序列化。如果类在默认情况下是可序列化的,会出现什么问题?最好将所有类标记为可序列化的,除非: 它们永远不会跨越应用程序域。如果不需要序列化且类需要跨应用程序域,则从MarshallByRefObject派生该类 该类存储仅适用于该类当前实例的特殊指针。例如,如果类包含非托管内存或文件句柄,请确保将这些字段标记为非序列化或根本不序列化该类 某些数据成员包含敏感信息。在这种情况下,最好只实现ISerializable

开发人员必须通过显式使用
SerializableAttribute
来“选择”使类可序列化。如果类在默认情况下是可序列化的,会出现什么问题?

最好将所有类标记为可序列化的,除非:

  • 它们永远不会跨越应用程序域。如果不需要序列化且类需要跨应用程序域,则从MarshallByRefObject派生该类
  • 该类存储仅适用于该类当前实例的特殊指针。例如,如果类包含非托管内存或文件句柄,请确保将这些字段标记为非序列化或根本不序列化该类
  • 某些数据成员包含敏感信息。在这种情况下,最好只实现ISerializable并序列化所需的字段

Ref:

可序列化类意味着它们具有某种状态,可以写入外部位置并再次读取。对于许多毫无意义的类,线程有什么样的状态,可以成功序列化


这有点哲学,但按照惯例,类的默认类型是不可序列化的,除非您明确定义“这个类可以序列化”.

我假设类在默认情况下是不可序列化的,因为无法保证使用反射将对象的状态转储到流中是有意义的。如果您的对象保持与数据库或通信端口的开放连接,该怎么办?每当通过反序列化前一个对象的实例来构造新对象时,最终将得到一个无用的对象

另外,您必须考虑,每当类是可序列化的,运行库都坚持其所有成员变量也是可序列化的,除非它们显式标记为否则。对于开发人员来说,让序列化成为一种选择加入功能要容易得多,而不是强迫他们选择退出某些成员


最后,类中可能有某些字段包含私有或敏感信息。必须显式地将类标记为可序列化可确保您不会意外地向世界公开您不想公开的内容(无论是数据还是实现)的细节。

IMO[serializable]令人困惑,主要是因为大多数序列化实际上都不需要它。我的意思是:有更多的代码使用XmlSerializer(包括asmx)、DataContractSerializer(包括WCF)、JavaScriptSerializer(包括MVC的JsonResult)或protobuf net之类的东西。[Serializable]主要是BinaryFormatter,从我看到的情况来看,它肯定在下降。而且有很多很好的理由

至于原因:其他答案解决了这个问题,但序列化某些内容并不总是有意义的。当然,实体对象可以充当DTO,但这很难以健壮的方式检测到


因此,在我看来,对我是否[可序列化]的影响可以忽略不计,但我同意默认设置:您应该知道您正计划序列化某些内容。在某些情况下,这种序列化意味着额外的工作(特别是一些序列化程序不运行ctor/init代码,因此您需要知道如何适当地准备字段)。

Liskov替换原则意味着,如果一个类是可序列化的,那么所有派生类也应该是可序列化的。如果类在默认情况下是可序列化的,那么在不违反Liskov替换原则的情况下派生不可序列化的类是非常困难的。

这正是这个问题的答案:-DBTW,我认为这个建议完全是错误的。将一个类标记为可序列化是没有意义的,除非这确实有意义,否则该类将需要支持它,并且是以支持它的方式编写的。-1-没有回答这个问题。“什么可能出错”和“为什么默认情况下不可序列化”。你回答了“我什么时候应该也不应该将事情标记为可序列化”。@Rob泄漏敏感信息不是你问题的答案吗??这不是我们使用ModelView而不是向客户公开模型的原因之一吗???@downvorters我不理解downvorters。因为答案明确列出了我们不应该使类可序列化的情况。这意味着在默认情况下使所有类都可序列化不是一个正确的决定,可能是有害的。