Odpowiedź zależy od konkretnie, co próbujesz osiągnąć w metodzie klonowania.
Jeśli chcesz utworzyć nową instancję bieżącej klasy bez faktycznego kopiowania żadnej z właściwości (co brzmi tak, jakbyś był zainteresowany zrobieniem na podstawie przykładowego kodu i opisu), to proste rozwiązanie to:
Public Class Foo
Implements ICloneable
Public Function Clone() As Object Implements System.ICloneable.Clone
Return Activator.CreateInstance(Me.GetType)
End Function
End Class
można przetestować, że nazywa się to poprzez dodanie wiadomość (albo jakiś debug lub wyjście) w Bar:
Public Class Bar
Inherits Foo
Public Sub New()
MsgBox("Test")
End Sub
End Class
Jeśli masz Option Strict On
, który gorąco polecam, kod w głównym będzie:
Sub Main()
Dim x As New Bar
Dim y As Bar = DirectCast(x.Clone, Bar)
End Sub
Jednakże, jeśli jesteś zainteresowany kopiowanie wartości członkowskich z bieżącej klasy, można użyć MemberwiseClone:
Public Class Foo
Implements ICloneable
Public Function Clone() As Object Implements System.ICloneable.Clone
Return Me.MemberwiseClone
End Function
End Class
Jednak ta stworzy tylko płytką kopię będzie skopiować odniesienia i nie wywoła konstruktora na pasku. Gdy używamy MemberwiseClone w ten sposób możemy zawsze dodać przeciążać metody, które mogą być używane przez spadkobierców wykonać porządki po Klon:
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
Wreszcie, jeśli płytkie kopiowanie lub czynienia ze skopiowanych odniesienia nie ma Cię lubić, można wykonać głęboką kopię używając tani, ale bardzo skuteczny trik: serializacji i deserializacji za pomocą 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
wymaga to zajęcia być możliwy do serializacji, ale to jest łatwe do zrobienia.
+1 ale nie podoba mi się ten styl VB; mimo że kompilator tego nie upoważnia, powinieneś zakwalifikować swoje wywołania funkcji za pomocą nawiasów, aby odróżnić je od dostępu do właściwości: to, wpisz 'Me.GetType()' zamiast 'Me.GetType' itd. –
@KonradRudolph: Dzięki za +1. Zgadzam się i zawsze podążam za tym w kodzie produkcyjnym, ale po prostu wyrzuciłem razem szybką próbkę, uznałem, że będzie w porządku. –