2010-12-16 31 views
0

我的程序决定分配指针而不是制作对象的副本,我不知道为什么。我有这样的事情:VB.net 3.5 assignmet操作员分配指针而不是复制?

Public Class Foo 
     Private myFooData As New List(Of FooData) 

     Public Sub New(ByVal newFooData As List(Of FooData)) 
      myFooData = newFooData 
     End Sub 

     Public Property FooValues() As List(Of FooData) 
      Get 
       Return myFooData 
      End Get 
      Set(ByVal value As List(Of FooData)) 
        myFooData = value 
      End Set 
     End Property 
    End Class 

而且它使用的是这样的:

Public Sub Dosomething() 
     Dim mainFoo as new Foo 

     For x = 1 to 10 
      mainFoo.FooValues(x) = New FooData 
     Next 

     Dim originalFoo as new Foo 
     originalFoo.FooValues = mainFoo.FooValues.Take(3).ToList 

     Dim newFoo as new Foo 
     newFoo.FooValues = originalFoo.FooValues 

     newFoo.FooValues(1) += 1 
    End Sub 

非常简单,但基本上我在做什么。因此,出于某种原因,当我在newFoo.FooValues中更改项目时,originalFoo.FooValues也会更改,而mainFoo则不会。我试着分配整个对象,并得到相同的结果。任何想法,为什么这可能会发生,以及如何解决它?

回答

2

这是.Net中的赋值应该如何工作。

当您在第二个片段的中间调用.ToList()时,您的代码遍历该集合并将副本复制到一个全新的列表中。这就是为什么你的mainFoo对象是“受保护的”—你创建了一个新的实例。如果被复制的FooData项目本身是对象的引用(提示:它们可能是),那么只有引用被复制。唯一的例外是字符串和值类型(基元和结构),或者如果您手工编写它。

它通常是一个好主意列表属性,使属性只读:

Public Property FooValues() As List(Of FooData) 
    Get 
     Return myFooData 
    End Get 
End Property 

这仍然会让你操作列表中你的心脏的内容,但会阻止您完全从下出切换列表实例班上。从类作为属性暴露的其他复杂类型也是如此。

你不想做的一件事就是将它改为结构而不是类。这看起来可能起初只是你想做的事,但它会在以后给你带来其他问题。

+0

FooData是另一个具有两个setable属性的类,都是小数。我已经尝试使用.ToList()时,将原始FooValues分配给新的FooValues和属性的集合,但它仍然工作相同,所以我假设你必须做某种选择或筛选以获得它来创建副本。 – Loscas 2010-12-16 19:35:05

+0

@Loscas没有办法让它自动创建副本 - 复制数据效率低下且设计不佳(它促进了可能过时的数据的工作)。 – 2010-12-16 19:36:41

1

当使用Foo.FooValues时,您可以指定Foo s中内部使用的List(Of FooData)的引用 - 并且没有值!

让我们考虑的步骤

Dim mainFoo as new Foo 

mainFoo现在有自己的后备名单。

originalFoo.FooValues = mainFoo.FooValues.Take(3).ToList 

originalFoo被分配一个新的支持列表存储一些mainFoo值的。

newFoo.FooValues = originalFoo.FooValues 

曾经有它自己的靠山名单newFoo,但现在,它采用了一个originalFoo用途。完全相同(通过指针)并且没有副本。

因此改变newFoo将改变originalFoo而不是mainFoo它有自己的列表。

因为我不知道你想达到毕竟什么,我不知道如何修复的代码,但你看,这是不是一个好主意,做一些后台列表访问即转让。

因此我建议,以保持列表不变私人,只是给索引访问。

+1

+1。但我会补充说,在VB中的引用类型,赋值操作符ALWAYS分配指针。 – pipTheGeek 2010-12-16 19:10:36

+0

所以你说,即使属性的设置值是byVal,它将它视为byRef? – Loscas 2010-12-16 19:21:29

+1

@Loscas - 在.Net中,你的变量大多只是引用。所有ByVal的意思是,引用本身是按值复制的。有很多理由说明为什么这会更好。 – 2010-12-16 19:26:36