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

The answer depends on specifically what you are trying to accomplish in the cloning method.

If you want to create a new instance of the current class without actually copying any of the properties (which is sounds like you may be interested in doing based on the sample code and description), then the simple solution is:

Public Class Foo
    Implements ICloneable

    Public Function Clone() As Object Implements System.ICloneable.Clone
        Return Activator.CreateInstance(Me.GetType)
    End Function
End Class

You can test that this is called by adding a message (or some sort of debug or output) in Bar:

Public Class Bar
    Inherits Foo

    Public Sub New()
        MsgBox("Test")
    End Sub

End Class

If you have Option Strict On, which I strongly recommend, the code in main would be:

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

However, if you are interested in copying the member values from the current class, you can use MemberwiseClone:

Public Class Foo
    Implements ICloneable

    Public Function Clone() As Object Implements System.ICloneable.Clone
        Return Me.MemberwiseClone
    End Function
End Class

However, this will only create a shallow copy, will copy references, and will not invoke the constructor on Bar. When we use MemberwiseClone in this manner, we always add an overridable method that can be used by inheritors to perform post-clone cleanup:

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

Finally, if shallow copying or dealing with copied references is not to you liking, you can perform a deep copy using a cheap, but very effective trick: serialization and deserialization using the 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

This requires that the classes be serializable, but that is easy to do.

于 2012-12-29T23:55:14.910 回答