La risposta dipende in particolare da cosa si sta tentando di ottenere nel metodo di clonazione.
Se si desidera creare una nuova istanza della classe corrente senza effettivamente copiare nessuna delle proprietà (che potrebbe sembrare interessante in base al codice di esempio e alla descrizione), la soluzione semplice è:
Public Class Foo
Implements ICloneable
Public Function Clone() As Object Implements System.ICloneable.Clone
Return Activator.CreateInstance(Me.GetType)
End Function
End Class
è possibile verificare che questo è chiamato con l'aggiunta di un messaggio (o una sorta di debug o di uscita) in bar:
Public Class Bar
Inherits Foo
Public Sub New()
MsgBox("Test")
End Sub
End Class
Se avete Option Strict On
, che consiglio vivamente, il codice principale sarebbe:
Sub Main()
Dim x As New Bar
Dim y As Bar = DirectCast(x.Clone, Bar)
End Sub
Tuttavia, se siete interessati a copiare i valori dei membri della classe corrente, è possibile utilizzare MemberwiseClone:
Public Class Foo
Implements ICloneable
Public Function Clone() As Object Implements System.ICloneable.Clone
Return Me.MemberwiseClone
End Function
End Class
Tuttavia, questo sarà solo creare una copia, sarà copiare i riferimenti, e non invocherà il costruttore su Bar. Quando usiamo MemberwiseClone in questo modo, aggiungiamo sempre un metodo override, che può essere utilizzato da eredi per eseguire post-clone di pulizia:
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
Infine, se la copia superficiale o trattare con riferimenti copiati non è a voi che gradite, è possibile eseguire una copia completa utilizzando un trucco a buon mercato, ma molto efficace: la serializzazione e deserializzazione utilizzando il 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
Ciò richiede che le classi siano serializzabili, ma che è facile da fare.
+1 ma non mi piace questo stile di VB; anche se il compilatore non lo impone dovresti qualificare le tue chiamate di funzione con parentesi per distinguerle dagli accessi di proprietà: cioè scrivere 'Me.GetType()' invece di 'Me.GetType' ecc. –
@KonradRudolph: Grazie per il +1. Sono d'accordo e seguo sempre questo nel codice di produzione, ma per aver semplicemente riunito un campione veloce, ho pensato che sarebbe andato tutto bene. –