2010-12-16 34 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