5

低音クラスの任意の派生クラスのオブジェクトを構築するメソッドを持つことはvb.netで可能ですか?このコードでは、x.CloneはBarオブジェクトを返す必要があります。両方の異なるオブジェクトタイプを持つ両方のクラスのコードを複製する唯一の方法です。

Module Module1

    Sub Main()
        Dim x As New Bar
        Dim y As Bar = x.Clone
    End Sub

End Module

Public Class Foo
    Implements ICloneable
    Public Function Clone() As Object Implements System.ICloneable.Clone
        Clone = Me.new() 'fails to compile as not in a constructor
        Clone = new Foo 'constructs a new foo in the derived class
    End Function
End Class

Public Class Bar
    Inherits Foo
    'additional implementation
    'but no addition fields
End Class
4

1 に答える 1

3

答えは、クローン作成方法で何を達成しようとしているのかによって異なります。

プロパティを実際にコピーせずに現在のクラスの新しいインスタンスを作成する場合(サンプルコードと説明に基づいて作成することに興味があるようです)、簡単な解決策は次のとおりです。

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

これには、クラスがシリアル化可能である必要がありますが、それは簡単です。

于 2012-12-29T23:55:14.910 に答える