C# 为什么必须用属性[serializable]标记类?

C# 为什么必须用属性[serializable]标记类?,c#,serialization,attributes,serializable,C#,Serialization,Attributes,Serializable,考虑到您可以将任何文档转换为字节数组并保存到磁盘,然后将文件重建为其原始形式(只要文件名等有元数据) 为什么必须用[Serializable]等标记类?这和“元数据”类型信息的想法是一样的,因此当您将对象强制转换到其类时,所有内容都正确映射了吗?它向序列化程序指示您希望该类被序列化,因为您可能不希望所有属性或类都被序列化。首先,您不必这样做 它只是一个命令,告诉序列化程序该类由它可以序列化(可能是真的,也可能不是真的)的项组成,也就是说,它可以使用默认序列化 XMLSerializer对类有一个

考虑到您可以将任何文档转换为字节数组并保存到磁盘,然后将文件重建为其原始形式(只要文件名等有元数据)


为什么必须用
[Serializable]
等标记类?这和“元数据”类型信息的想法是一样的,因此当您将对象强制转换到其类时,所有内容都正确映射了吗?

它向序列化程序指示您希望该类被序列化,因为您可能不希望所有属性或类都被序列化。

首先,您不必这样做

它只是一个命令,告诉序列化程序该类由它可以序列化(可能是真的,也可能不是真的)的项组成,也就是说,它可以使用默认序列化

XMLSerializer
对类有一个零参数构造函数的额外要求


还有其他一些序列化程序使用协定进行序列化(例如),它们为您提供了对序列化的更多控制,而不仅仅是将类标记为
可序列化的
。通过实现接口,您还可以获得更多的控制。

基本上是元数据指示类可以序列化,仅此而已


许多框架序列化程序都需要它,它们拒绝处理未应用此属性的类型。

序列化可能会造成安全漏洞,并可能受到版本控制问题的困扰。除此之外,对于某些类来说,序列化的想法完全是胡说八道

有关详细信息,请参阅的优秀答案,尤其是和。它们使序列化成为您必须明确选择的功能


作为对比,这个问题的公认答案表明,类在默认情况下应该是可序列化的。

二进制序列化功能非常强大,它可以创建类的实例,而无需运行构造函数,并且可以在类中设置声明为私有的字段。常规代码当然不能做到这一点。通过应用[Serializable]属性,您可以显式地允许它处理您的私有部分。并且您只隐式地将该权限授予BinaryFormatter类

XML序列化不需要这种类型,它只序列化公共成员


DataContractSerializer也可以序列化私有成员。因此,现在需要使用[DataContract]属性再次明确确认。

我认为这是一个提醒,我将允许序列化该类。因此,您不会隐式序列化不应该序列化的内容

不知道这是设计师的意图


顺便说一句,我喜欢BinaryFormatter,并尽可能多地使用它。它几乎可以自动处理大部分内容(比如用遍布整个图形的循环引用重建复杂的对象图)。

它只能应用于类型,不是成员。我认为这有点误导-听起来好像如果我有一个可序列化的类a和一个不可序列化类型的成员B,那么成员B将被忽略。事实上,序列化将抛出。XmlSerializer不需要SerializableAttribute@Oded:-1直到您编辑您的答案以显示
XmlSerializer
不关心
[Serializable]
@Matthew Whited,@John Saunders-谢谢您的更正。答案更新。我只是想推荐Krzysztof Cwalina和Brad Abrams在“框架设计指南”中关于序列化的一章,从框架设计师的角度解释了什么时候使用什么。你必须这样做。否则BinaryFormatter将不会移动!我的意思是,它会影响你…为了完整性,如果你正在存储数据(到磁盘等),我不建议使用
BinaryFormatter
(这是最重要的)。大多数其他序列化程序都会完成这项工作,但在您更改类型时不会咬到您。然而,
BinaryFormatter
是迄今为止最强大的。它序列化字段和属性,序列化整个对象(包括私有字段),支持循环引用,并且绕过对象构造,因此不需要公共默认构造函数,例如
XmlSerializer
都不提供。如果你想改变类型,你必须处理版本控制。相反:-1直到答案被纠正:与流行的观点相反,DataContractSerializer不会强迫你标记一个类[DataContract],它是一种选择。当没有属性装饰类时,默认情况下序列化程序将推断所有公共读/写属性和字段的约定。请参阅MSDN:这句话中的“public”一词似乎让您感到困惑。为了以防万一,DataContractSerializer不一定需要[DataContract]属性。[Serializable]就可以了(通过它,您也不需要标记需要由[DataMember]序列化的所有内容)。有趣的事实:在类的帮助下,您也可以创建未初始化的对象!邪恶!:)但无法与非.NET域进行互操作。