我在使用BinaryFormatter.Serialize时遇到了问题。
我有这种通用扩展方法通过二进制序列化来“克隆”对象:
<Extension()>
Public Function CloneViaSerialization(ByRef Obj as System.Object)
Dim NewObj As System.Object
Using MS As New System.IO.MemoryStream
Dim Formatter as New BinaryFormatter
Formatter.Serialize(MS, Obj)
Debug.WriteLine("MS LENGTH = " & MS.Length)
MS.Position = 0
NewObj = Formatter.Deserialize(MS)
End Using
Return NewObj
End Function
我还有一个名为“Mode”的类,其方法为“Clone”,如下所示:
Friend Function Clone()
Dim NewMode as Mode = Me.CloneViaSerialization
Return NewMode
End Function
在我的GUI中,我有一个允许克隆选定Mode对象的函数。用户输入一系列新的模式名称,例程循环通过这些新名称创建所选模式的克隆:
Private Sub MakeClones(ByRef ModeToClone as Mode, ByVal CloneNames as List(Of String))
For Each CloneName as String in CloneNames
Dim NewMode as Mode = ModeToClone.Clone
NewMode.Name = CloneName
ParentObject.Modes.Add(NewMode)
Next
End Sub
因此,基本上应该创建所选Mode对象的一个或多个克隆,将Name属性设置为正确的值,并将新的Mode对象添加到父对象。这涉及对Mode.Clone方法的X次调用以及对CloneViaSerialization扩展方法的X调用。
这是我的问题。在多次调用CloneViaSerialization期间,MemoryString长度(显示在Debug.WriteLine语句中)几乎是前一次调用的两倍。例如,制作五个克隆,调试输出为:
MS LENGTH = 106882 MS LENGTH = 188048 MS LENGTH = 350482 MS LENGTH = 675350 MS LENGTH = 1325086
这是杀戮表现。任何超过7或8个克隆的东西都会让应用程序停止运行。为什么会这样? USING块应该确保处理MemoryString,对吧?不应该每次都创建一个新的MemoryString吗?我认为,因为相同的原始Mode对象是序列化的源,MemoryString长度将是相同的。有任何想法吗?我在这里缺少什么?
提前致谢!
答案 0 :(得分:0)
我不确定为什么你的CloneViaSerialization
消耗了大量内存,你发布的代码对我来说似乎没问题(尽管一种可能的解释可能只是克隆的数据很大)。另一种方法是在ICloneable
课程上实施Mode
,并设置Clone
函数以对对象进行深层复制。
Public Class Mode
Implements ICloneable
Private m_Prop1 As String
Public Property Prop1() As String
Get
Return m_Prop1
End Get
Set
m_Prop1 = Value
End Set
End Property
Private m_Prop2 As Int16
Public Property Prop2() As Int16
Get
Return m_Prop2
End Get
Set
m_Prop2 = Value
End Set
End Property
Private m_Prop3 As List(Of Int16)
Public Property Prop3() As List(Of Int16)
Get
Return m_Prop3
End Get
Set
m_Prop3 = Value
End Set
End Property
Public Function Clone() As Object Implements ICloneable.Clone
Dim objClone as Mode
objClone = MemberwiseClone()
If Not Me.Prop3 Is Nothing Then
objClone.Prop3 = new List(Of Int16)
objClone.Prop3.AddRange(Me.Prop3)
End If
Return objClone
End Function
End Class
请注意,在Clone
函数中,我们需要单独复制List(Of Int16)
。 MemberwiseClone
会将引用复制到它创建的新对象中,因此,如果我们不创建新的List(Of Int16)
并手动复制值,那么我们将最终引用原始列表。克隆
我还应该指出,有些人可能在实施ICloneable
时遇到问题并让它进行深层复制,因为MemberwiseClone
只执行浅拷贝。如果这让您感到困扰,那么您可以随时将Clone
重命名为DeepClone
并删除ICloneable
界面。
希望有所帮助。