1

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?

Steven Doggart
  • 43,358
  • 8
  • 68
  • 105
Recipe
  • 1,398
  • 3
  • 16
  • 29

1 Answers1

1

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
Steven Doggart
  • 43,358
  • 8
  • 68
  • 105
  • Thanks Steven. While I did solve this another way (the object was fundamentally changed), your solution would be a good approach. – Recipe Nov 05 '14 at 09:01