2010-12-16 9 views
0

私のプログラムは、オブジェクトのコピーを作成するのではなくポインタを割り当てることにしました。私はこのようなものがあります:VB.net 3.5代入演算子ではなくコピーする代わりにポインタを割り当てますか?

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のitemを変更すると、originalFoo.FooValuesも変更され、mainFooは変更されません。私はオブジェクト全体を割り当てようとしましたが、同じ結果が得られます。なぜこれが起こっている可能性があり、それを修正する方法は?

答えて

2

これは、.Netの割り当てがどのように動作するはずです。

2番目のスニペットの途中で.ToList()を呼び出すと、コードはセットを反復処理し、新しいリスト全体にコピーを作成します。これがあなたのmainFooオブジェクトが "保護されている"理由です—あなたは新しいインスタンスを作成しました。コピーされるFooData項目自体がオブジェクトへの参照(ヒント:おそらくそうです)の場合、参照のみがコピーされます。唯一の例外は文字列と値型(プリミティブと構造体)、または手作業でコード化する場合です。

これは、プロパティの読み取り専用を作るために、通常はリストのプロパティのために良いアイデアだ:

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

これはまだあなたがあなたの心のコンテンツにリストを操作できますが、あなたは完全に下からリストのインスタンスを切り替えることを防止しますクラス。クラスからプロパティとして公開される他の複合型についても同様です。

あなたがしたくないことは、これをクラスではなく構造に変更することです。これはあなたが最初にしたいことをするように思われるかもしれませんが、後であなたのために他の問題を引き起こすでしょう。

+0

FooDataは、2つの設定可能なプロパティ、つまり両方の小数を持つ別のクラスです。私は元のFooValuesを新しいFooValuesとプロパティのセットに割り当てるときに.ToList()を使用しようとしましたが、それでも同じように動作しますので、何らかの選択やフィルタを行う必要があると仮定しますそれはコピーを作成することです。 – Loscas

+0

@ Loscasコピーを自動的に作成する方法はありません。データをコピーするのは効率が悪く、デザインが悪い(失効したデータを扱うことを促進します)。 –

1

Foo.FooValuesを使用している場合は、Fooに内部的に使用されているList(Of FooData)への参照を割り当てます。

のは、ステップ

Dim mainFoo as new Foo 

mainFooを考えるには、今、独自のバッキングリストを持っています。

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

originalFoomainFooの値の一部を格納し、新たなバッキングリストが割り当てられます。

newFoo.FooValues = originalFoo.FooValues 

newFoo、独自のバッキングリストを持っていたが、今、それは1つのoriginalFoo用途を使用しています。全く同じもの(ポインタによるもの)とコピーなし。

したがって、newFooを変更するとoriginalFooが変更されますが、mainFooには独自のリストがあります。

結局のところ、達成しようとしていることがわからないので、のコードをに修正する方法はわかりませんが、ご覧のとおり、バッキングリストをアクセス可能にすることはできません。

したがって私は、インデックスへのアクセスを与え、リスト不変プライベートを維持するためにアドバイスしたいです。

+1

+1。しかし、私はVBの参照型のために代入演算子は常にポインタを割り当てることを追加します。 – pipTheGeek

+0

プロパティの設定値がbyValであってもbyRefとして扱っていると言っていますか? – Loscas

+1

@ Loscas - .Netでは、あなたの変数はたいていは単なる参照です。すべてのByValの意味は、参照自体が値によってコピーされるということです。これがなぜ良いのか、良い理由があるのです。 –

関連する問題