“(无需手动将所有属性从一个复制到另一个)”
真的吗?
我认为在某个时候,您将不得不编写更复杂的代码来执行此操作...
序列化/反序列化...大部分时间都很方便。我使用了这个..直到我在一个类中添加了一个属性,而没有在其他类中添加它们的对应项。像 Point2D 和 X 和 Y 作为双精度类,Vector2D 使用 X 和 Y 作为双精度或 Displacement2D 使用 X 和 Y 作为双精度...直到我在 Vector2D 中添加了属性 Length... 以及以后, Distance 在 Displacement2D.. 中:/
定义对象类型的属性(枚举)。同样在这里:在某一时刻,为了便于使用,您可以将成员添加到与其他类无关的一个类中。 :/ 这使得你的对象要么无法成长/进化,要么与未使用/假成员一起变得奇怪......
所以最后,我认为您必须在“冻结”类的当前状态(成员)或编写处理转换所需的每个代码以及在需要时更新这些代码(添加/编辑成员)之间做出选择)
用 CType 扩展怎么样?
Public Class StopWatch
Inherits TimeRecord
' ...
Public Shared Widening Operator CType(ByVal HistoricInstance As Historic) As StopWatch
Dim NewStopWatch As StopWatch
If HistoricInstance IsNot Nothing Then
NewStopWatch = New StopWatch(...)
' Set NewStopWatch Properties here...
' ...
Return NewStopWatch
Else
Return Nothing
End If
End Operator
End Class
还有:
Public Class Historic
Inherits TimeRecord
' ...
Public Shared Widening Operator CType(ByVal StopWatchInstance As StopWatch) As Historic
Dim NewHistoric As Historic
If StopWatchInstance IsNot Nothing Then
NewHistoric = New Historic(...)
' Set NewHistoric Properties here...
' ...
Return NewHistoric
Else
Return Nothing
End If
End Operator
End Class
注意:如果您将属性添加到 StopWatch 而不是 Historic,则 StopWatch CType 运算符将变为 Narrowing 而不是 Widening。
当然,每次您将一个类转换为另一个类时,这都会创建该类的一个新实例。有时,当您希望两个类都使用相同的包含对象(而不是新实例)和几个月后,这并不方便,您忘记了您已经编写了扩展运算符以创建所有成员的新实例...
假设您有一个 StopWatch 类型的 MyStopWatch 类,以及在构造函数中设置为 Date.Now 的属性 InitializationDateTime..
MyStopWatch = New StopWatch() ' .InitializationDateTime = Date.Now
' do some stuff...
MyHistoric = CType(MyStopWatch, Historic) ' where MyHistoric.InitializationDateTime = Date.Now
使用上面的代码,即使你假设你已经正确地将 MyTimeRecord 转换为 MyHistoric,你也会有不同的属性 InitializationDateTime 值,这是因为 CType 稍后创建了一个 Historic 实例 比 MyTimeRecord 初始化的时间。
那怎么办?序列化、TypeCode 属性/枚举或 CType 扩展?
Plutonix 有另一种方式:
Public Class StopWatch()
Public Sub New(ByVal HistoricInstance As Historic)
' Copy Properties values here...
End Sub
End Class
' Do the same for Historic Class.
或者你也可以制作函数(VB.net的意思)
Public Class StopWatch()
Public Function ToHistoric() As Historic
Dim NewHistoric As New Historic()
' .. set NewHistoric Properties values here
Return NewHistoric
End Function
End Class
但结果是一样的:您必须编写代码来一一设置属性值。好处是:您编写一次代码,最终更新它,但您可以随时使用它,只需一行代码...
DirectCast 很方便,但容易导致运行时崩溃。
TryCast 很有趣,但无论如何你都必须检查转换失败。 :/
还有其他方法可以做到,但是从现在开始,建议的方法之一是否足够有用,或者您有一些特定要求,例如上面的问题?