答えは、クローン作成方法で何を達成しようとしているのかによって異なります。
プロパティを実際にコピーせずに現在のクラスの新しいインスタンスを作成する場合(サンプルコードと説明に基づいて作成することに興味があるようです)、簡単な解決策は次のとおりです。
Public Class Foo
Implements ICloneable
Public Function Clone() As Object Implements System.ICloneable.Clone
Return Activator.CreateInstance(Me.GetType)
End Function
End Class
Barにメッセージ(またはある種のデバッグまたは出力)を追加することで、これが呼び出されることをテストできます。
Public Class Bar
Inherits Foo
Public Sub New()
MsgBox("Test")
End Sub
End Class
を持っている場合Option Strict On
、これは私が強くお勧めしますが、mainのコードは次のようになります。
Sub Main()
Dim x As New Bar
Dim y As Bar = DirectCast(x.Clone, Bar)
End Sub
ただし、現在のクラスからメンバー値をコピーすることに関心がある場合は、MemberwiseCloneを使用できます。
Public Class Foo
Implements ICloneable
Public Function Clone() As Object Implements System.ICloneable.Clone
Return Me.MemberwiseClone
End Function
End Class
ただし、これは浅いコピーを作成するだけで、参照をコピーし、Barのコンストラクターを呼び出しません。MemberwiseCloneをこのように使用する場合、継承者がクローン後のクリーンアップを実行するために使用できるオーバーライド可能なメソッドを常に追加します。
Public Class Foo
Implements ICloneable
Public Function Clone() As Object Implements System.ICloneable.Clone
Dim oObject As Foo
oObject = DirectCast(Me.MemberwiseClone, Foo)
oObject.PostCloneCleanup()
Return oObject
End Function
Protected Overridable Sub PostCloneCleanup()
End Sub
End Class
Public Class Bar
Inherits Foo
Public Sub New()
MsgBox("Test")
End Sub
Protected Overrides Sub PostCloneCleanup()
MsgBox("PostCloneCleanup")
End Sub
End Class
最後に、浅いコピーまたはコピーされた参照の処理が気に入らない場合は、安価で非常に効果的なトリックを使用してディープコピーを実行できます。BinaryFormmaterを使用したシリアル化と逆シリアル化:
Public Function CreateDeepCopy(Of T)(ByVal oRecord As T) As T
If oRecord Is Nothing Then
Return Nothing
End If
If Not oRecord.GetType.IsSerializable Then
Throw New ArgumentException(oRecord.GetType.ToString & " is not serializable")
End If
Dim oFormatter As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
Using oStream As IO.MemoryStream = New IO.MemoryStream
oFormatter.Serialize(oStream, oRecord)
oStream.Position = 0
Return DirectCast(oFormatter.Deserialize(oStream), T)
End Using
End Function
これには、クラスがシリアル化可能である必要がありますが、それは簡単です。