This is the situation:
Class A
Implements ICloneable
Public Property Children As List(Of Child)
Public Function Clone() As Object Implements ICloneable.Clone
Return New A With {
.Children = Children.Select(Function(c) DirectCast(c.Clone(), Child)).ToList()
}
End Function
End Class
Class Child
Implements ICloneable
Public Property Parent As A
Public Function Clone() As Object Implements ICloneable.Clone
Return New Child With {
.Parent = DirectCast(Parent.Clone(), A)
}
End Function
End Class
The actual object is more complex, having several levels.
I'm not sure how to solve this because, at the moment, whenever you call Clone
on the parent A
class, you will end up with a circular reference.
How can I avoid this situation? Should I create my own Clone
function and pass along a parameter?
The simplest solution is to just have the Child
class not clone the Parent
property at all. When a Child
clones itself, it could either leave the Parent
property the same, or just leave it null. For instance:
Class Child
Implements ICloneable
Public Property Parent as A
Public Function Clone() As Object Implements ICloneable.Clone
Return New Child() With { .Parent = Me.Parent }
End Function
End Class
Then, when the parent A
class clones itself, it could set the Parent
property of all the cloned children, like this:
Class A
Implements ICloneable
Public Property Children As List(Of Child)
Public Function Clone() As Object Implements ICloneable.Clone
Return New A() With
{
.Children = Me.Children.Select(
Function(c)
Dim result As Child = DirectCast(c.Clone(), Child))
result.Parent = Me
Return result
End Function).ToList()
}
End Function
End Class
Alternatively, as you suggested, you could make your own Clone
method which takes the parent object as a parameter:
Class Child
Public Property Parent as A
Public Function Clone(parent As A) As Object
Return New Child() With { .Parent = parent }
End Function
End Class
It won't implement ICloneable
, but as long as you don't need it to be interchangeable with other types of ICloneable
objects, then that won't matter. Similarly, you could just overload your constructor:
Class Child
Public Property Parent as A
Public Sub New()
End Sub
Public Sub New(childToClone As Child, parent As A)
' Copy other properties from given child to clone
Me.Parent = parent
End Sub
End Class