【问题标题】:Binary Serialization of references using BinaryFormatter使用 BinaryFormatter 对引用进行二进制序列化
【发布时间】:2026-02-10 08:05:02
【问题描述】:

鉴于以下类结构,Bar 是否会按预期进行序列化/反序列化?

public class Foo { int x; string y; }

[Serializable]
public class Bar {
   Foo[] AllFoos;
   Foo SelectedFoo;

   public Bar(Foo[] allFoos, int selectedFooIndex) { 
     this.AllFoos = allFoos; 
     this.SelectedFoo = allFoos[selectedFooIndex]; 
   } 
}

我对几件事感到好奇:

1) BinaryFormatter 是否要求 Bar 类用 [Serializable] 属性修饰或实现 ISerializable 接口?

2) Foo 类是否也需要用 [Serializable] 属性修饰?

3) 如果 Bar 简单地用 [Serializable] 属性修饰,字段 Bar.SelectedFoo 是否会正确地保持其对数组的引用?还是我会得到一份 Foo 的副本?

【问题讨论】:

    标签: .net serialization reference binaryformatter


    【解决方案1】:

    1) BinaryFormatter 是否要求 Bar 类用 [Serializable] 属性修饰或实现 ISerializable 接口?

    是的,如果要使用 BinaryFormatter 来序列化 Bar 实例,则可以。

    2) Foo 类是否也需要用 [Serializable] 属性修饰?

    是的,除非您创建不涉及序列化 Foo 对象实例的自定义序列化机制。例如,您可以分别序列化 x 和 y 组件,并在反序列化代码中从它们创建一个新的 Foo 实例。否则,它必须具有属性或接口。

    3) 如果 Bar 简单地用 [Serializable] 属性修饰,字段 Bar.SelectedFoo 是否会正确地保持其对数组的引用?还是我会得到一份 Foo 的副本?

    如果我没记错的话,数组不能像这样序列化。您必须提供自己的机制(通过 ISerializable 接口)来写入和读取数组。

    但是,一般来说,如果使用 BinaryFormatter 序列化具有相互引用的可序列化对象的图形,那么它将正确地重新创建引用而不会复制对象。这也应该包括您在自定义序列化代码中指定的对象,只要您使用 Serializable 装饰您的 Foo 并将相同的对象实例从数组和字段传递给格式化程序。

    【讨论】: