9

オブジェクトのディープ コピーを実行する方法を教えてください。

これが私のコードです:

Option Explicit On
Option Strict On

<Serializable> Public Class [Class]
Private _Name As String
Private _ListOfFields As New List(Of Field)

Public Property Name As String
    Get
        Return _Name
    End Get
    Set(value As String)
        _Name = value
    End Set
End Property

Public Property ListOfFields As List(Of Field)
    Get
        Return _ListOfFields
    End Get
    Set(value As List(Of Field))
        _ListOfFields = value
    End Set
End Property

Public Function Clone() As [Class]
    Return DirectCast(Me.MemberwiseClone, [Class])
End Function

End Class

フィールドは、私も自分で書いたクラスです。

Clone() 関数がディープ コピーを返すようにするには、何を変更する必要がありますか?

4

2 に答える 2

9

このヘルパー関数を呼び出すことで、任意のクラスのクローンを作成できます。

Function DeepClone(Of T)(ByRef orig As T) As T

    ' Don't serialize a null object, simply return the default for that object
    If (Object.ReferenceEquals(orig, Nothing)) Then Return Nothing

    Dim formatter As New BinaryFormatter()
    Dim stream As New MemoryStream()

    formatter.Serialize(stream, orig)
    stream.Seek(0, SeekOrigin.Begin)

    Return CType(formatter.Deserialize(stream), T)

End Function

これは、クラスからのすべての情報をポータブル オブジェクトにシリアル化し、参照ポインターを切断するためにそれを書き換えることによって機能します。

: 渡されたクラスと、それがプロパティとして公開するその他のクラス<Serializable()>を使用するには、マークを付ける必要があります。BinaryFormatter.Serialize

独自のクラスで複製可能なメソッド自体を公開する場合は、メソッドを追加して、次のICloneableようにインターフェイスを実装できます。

<Serializable()>
Public Class MyClass : Implements ICloneable

    'NOTE - The Account class must also be Serializable
    Public Property PersonAccount as Account
    Public Property FirstName As String

    Function Clone(ByRef orig As MyClass) As MyClass Implements ICloneable.Clone

        ' Don't serialize a null object, simply return the default for that object
        If (Object.ReferenceEquals(orig, Nothing)) Then Return Nothing

        Dim formatter As New BinaryFormatter()
        Dim stream As New MemoryStream()

        formatter.Serialize(stream, orig)
        stream.Seek(0, SeekOrigin.Begin)

        Return CType(formatter.Deserialize(stream), T)

    End Function

End Class

: ICloneable は、ディープ クローンまたはシャロー クローンを実行しているかどうかを呼び出し元に示さないため、論争の的となっていることに注意してください。実際には、メソッドをクラスに追加できるようにするためにインターフェースは必要ありません。

于 2015-03-09T19:07:28.563 に答える
6

(余談ですが、私はおそらくあなたのクラスに「クラス」以外の名前を付けるでしょう)。

すべてを手動で行いたい場合は、次のような手順に従う必要があります。

  1. Field クラスにもディープ コピーClone()メソッドが実装されていることを確認してください。これをまだ行っていない場合は、そのClone()メソッドでタイプの新しいオブジェクトを作成Fieldし、現在のオブジェクトに基づいて各プロパティを設定する必要があります。Fieldクラスに他のクラス/複雑なタイプのプロパティがある場合(たとえば、自分で作成したクラス)、それらも実装Clone()する必要があり、それらを呼び出しClone()て新しいディープ コピーを作成する必要があります。
  2. クラスのClone()メソッドでは、たとえばそのコンストラクターを呼び出して、タイプ [Class] の新しいオブジェクトを作成します。
  3. Name新しいオブジェクトのNameプロパティを現在のオブジェクトのプロパティに設定します
  4. 新しいList(Of Field)を作成し、例のために listA と呼びましょう
  5. 現在のリストを繰り返し処理し、各リスト項目のクローンを listA に割り当てます。例えば:

For Each item in _ListOfFields
    listA.Add(item.Clone())
End

  1. その後、Clone()メソッドで作成したオブジェクトに新しいリスト (listA) を割り当てることができます

hereで説明されている VB.NET にある別の (おそらくより良い) 手作業によるアプローチがあります。

少しごまかしたい場合は、既存のオブジェクトをシリアル化してから、ここのテクニックのように新しいオブジェクトに逆シリアル化することができます

シリアライズしてからデシリアライズする手法が「最も簡単な」手法だと思います。

于 2013-03-23T06:49:05.560 に答える