我正在vb 2010中写一个项目 我的问题在这里:
Dim s1 As New List(Of blocks)
Dim s As New blocks
s.Type = blocks.Khane_Type.Block
s1.Add(s)
s = New blocks
s.Type = blocks.Khane_Type.Hadaf
s1.Add(s)
Dim s2 As List(Of blocks) = New List(Of blocks)
s2 = s1.GetRange(0, 2)
s1(0).Type = blocks.Khane_Type.Player
MsgBox(s2(0).Type.ToString)
当我更改s1列表中的值时,s2列表也会更改。为什么??????有什么问题?
答案 0 :(得分:0)
msdn.microsoft.com/en-us/library/21k0e39c%28v=vs.110%29.aspx
s2的元素仍然指向相同的底层对象(它是浅层副本)。
即。 s2包含与s1
的元素0,1和2相同的块对象实例的引用制作对象的完整副本取决于Block类的功能。您可能会发现http://msdn.microsoft.com/en-us/library/t63sy5hs.aspx基本概述了值类型和有用的引用类型之间的区别。
如果Block类只有值类型字段,那么成员克隆http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone%28v=vs.110%29.aspx就足够了(此链接也解释了浅拷贝和深拷贝之间的关键差异)。
如果它包含引用字段(例如对其他对象的引用),则应添加.Copy或.Clone方法。本质上,这样的方法将创建其类的新实例,将其值分配给新的类值字段(或首先执行成员克隆)并处理引用类型(如何取决于它们是什么)。
您应该开始一个新的问题来解释您的Block对象以及制作它的实例副本的最佳实践。
答案 1 :(得分:0)
s2是"浅拷贝"你的列表,这意味着复制指针而不是对象本身。如果你想复制"内容"你的对象(而不是指针),你应该做一个深拷贝。我准备了这个简单的工作示例,希望它有助于理解概念并修复代码。
Dim a As List(Of String) = New List(Of String)
a.Add("ciao")
a.Add("hi")
a.Add("hallo")
'shallow copy sc
Dim sc As List(Of String) = New List(Of String)
sc = a 'sc will store just the pointer of a. So, if a changes, sc changes as well since it still points to the object a.
'deep copy dc
Dim dc As List(Of String) = New List(Of String)
Using stream As New System.IO.MemoryStream()
Dim formatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
formatter.Serialize(stream, a)
stream.Seek(0, IO.SeekOrigin.Begin)
dc = formatter.Deserialize(stream) 'dc is storing the content of a in its own memory. It's a bit longer procedure because you need to create it a memory, but now even if a changes, dc will be the same.
End Using
a(1) = "goodbye"
MsgBox("sc(1) changed to " & sc(1) & " while dc(1) is still " & dc(1))
因此,按照上面的示例,如果用以下代码替换s2 = s1.GetRange(0,2)
,您将看到s2不会与s1一起更改,您可以根据需要更改s1而不会影响s2:< / p>
Using stream As New System.IO.MemoryStream()
Dim formatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
formatter.Serialize(stream, s1)
stream.Seek(0, IO.SeekOrigin.Begin)
s2 = formatter.Deserialize(stream)
End Using