Results 1 to 6 of 6

Thread: Deep Clone Help

  1. #1

    Thread Starter
    Fanatic Member clarkgriswald's Avatar
    Join Date
    Feb 2000
    Location
    USA
    Posts
    769

    Deep Clone Help

    I am jumping into a project that already has its object model built and in use. I am trying to make a DeepClone method on the object, but I am running into trouble due to the fact that the class inherits from Open.Collections.OrderedDictionary:


    VB.NET Code:
    1. Public MustInherit Class CollectionBase(Of TKey, TValue)
    2.     Inherits OrderedDictionary(Of String, TValue)


    And the OrderedDictionary is defined like this:

    VB.NET Code:
    1. Public Class OrderedDictionary(Of TKey, TValue)
    2.         Inherits DisposableBase
    3.         Implements IOrderedDictionary(Of TKey, TValue), IDictionary(Of TKey, TValue), ICollection(Of KeyValuePair(Of TKey, TValue)), IEnumerable(Of KeyValuePair(Of TKey, TValue)), IEnumerable

    I wanted to go with the simple binary formatter approach, but I can't seem to figure out how to handle this inheritance. It doesn't have to be binary formatter, it can be any approach.

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,043

    Re: Deep Clone Help

    I'm not sure that the binary formatter will work. For that to work, then every object has to be marked as serializable (if I remember right). The problem with that approach would be that you are using generics, so the actual types could be anything...including things that are not marked as serializable.

    The problem is that the other options also seem to have the same problem. When it comes to making a deep copy of a generic type, you run into the problem that some types might not lend themselves to forming deep copies. What comes to mind is to require that the type of the key and value could be restricted to just types that allowed for cloning, but there's no built-in indicator of whether or not a type allows cloning that I am aware of.

    To sum up: I don't see a clear way to do this and stick with generics. I'll be interested in seeing what others come up with.
    My usual boring signature: Nothing

  3. #3

    Thread Starter
    Fanatic Member clarkgriswald's Avatar
    Join Date
    Feb 2000
    Location
    USA
    Posts
    769

    Re: Deep Clone Help

    Quote Originally Posted by Shaggy Hiker View Post
    I'm not sure that the binary formatter will work. For that to work, then every object has to be marked as serializable (if I remember right). The problem with that approach would be that you are using generics, so the actual types could be anything...including things that are not marked as serializable.

    The problem is that the other options also seem to have the same problem. When it comes to making a deep copy of a generic type, you run into the problem that some types might not lend themselves to forming deep copies. What comes to mind is to require that the type of the key and value could be restricted to just types that allowed for cloning, but there's no built-in indicator of whether or not a type allows cloning that I am aware of.

    To sum up: I don't see a clear way to do this and stick with generics. I'll be interested in seeing what others come up with.
    Yup, that was the exact issue I was running into. I saw a solution that uses MemberwiseClone and reflection, but it kind of looked like a bit of magic in some areas.
    Not that this is ideal, but that about the explicit copying of each property manually - is there a way to do this to enforce that the "Copy" method is updated appropriately if new properties are added (e.g. using interfaces or something like that)? In other words, if someone were to add a property to the base class down the line, there would be a compile error until they implemented the new property in the copy method.

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,043

    Re: Deep Clone Help

    I don't believe there would be any way for that to be possible. An interface was what I thought of first, as did you, apparently, but that clearly won't work. You can make an interface that has a Clone method as a member. You can make it so that a class that is either key or value MUST implement that interface, but what you can't do is ensure that the class implements a Clone method that has a meaningful body. You can't do this because if you could, you'd have figured out how to enforce a bug-free program, and nobody has figured that out, yet. Furthermore, that's the problem with EVERY other potential solution that forces the user to implement a deep copy.

    Consider a simple interface:
    Code:
    Public MyInterFace
     Function Clone(someInput As T) As T
    End Interface
    and a simple class that implements it:
    Code:
    Public Class MyClass
     Implements MyInterface
    
     Public Function Clone(someInput As MyClass) As MyClass
        'Something here.
      End Function
    
    End Class
    That's as much as the compiler can enforce. They can't require that the body of the Clone method in MyClass be anything in particular. If the body of that method was simply:

    Return Me

    then the Clone is now a shallow copy. A complicated, slower, shallow copy, but still a shallow copy. On the other hand, if the body of the Clone method is just:

    Return Nothing

    It will compile, but now you don't even have a shallow copy. There is no way to prevent this, either.

    Worse, if the Clone method was an attempt at a deep copy, but the user screwed it up, and it was a buggy implementation of a deep copy, there wouldn't be any clear way to even know that it was buggy except through testing. If you could know that it was buggy, regardless of what the class implementing the interface was, then you'd be able to know that any arbitrary function was buggy, because the Clone method is just a function.

    So, I believe it is completely impossible to enforce a requirement of a deep copy on a class, because the user has to be able to screw it up, since we do that plenty. Since you can't detect all screw ups at compile time, you can't prevent them, nor can you differentiate between the user deliberately doing the wrong thing, or doing the wrong thing by mistake.
    My usual boring signature: Nothing

  5. #5

    Thread Starter
    Fanatic Member clarkgriswald's Avatar
    Join Date
    Feb 2000
    Location
    USA
    Posts
    769

    Re: Deep Clone Help

    Yup, we are thinking alike here...I find it strange that .NET doesn't have this support natively, obviously it's not trivial. Did you happen to take a look at that MemberwiseClone article? Thoughts on that?

  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,043

    Re: Deep Clone Help

    The problem with deep copies is that there is no commonality between classes. Most classes have roughly similar deep copy approaches, which is what both of the approaches in that article rely on. Some classes will NOT have the same deep copy approach. The problem with generics is that you can't be sure what type you will get. As long as all the types lend themselves to that memberwise clone approach, then you're all set. As soon as you get a type that doesn't work that way, things break.

    For example, suppose one of the members of the class holds something that really shouldn't be cloned deeply. Perhaps it's a reference to a read-only data structure with a size of a few gigabytes, or perhaps it's a database connection. A deep copy with that reference to the data structure would probably NOT copy the data structure. All copies could readily hold a reference to the same data structure, whereas cloning the read only data structure would gain you nothing and cost gigabytes. The memberwise clone approach would work, it would just come at an appalling cost. In the case of a class that held a database connection, I'm not sure what the memberwise clone would even do, but it certainly might not be ideal.

    So, most classes can be cloned in one of the ways that were shown in the article, but that assumes that the most appropriate way to clone the class is to clone all parts of the class. That will be true for the vast majority of classes, but it will not be true for a significant minority of classes. For this reason, there is no standard deep copy method, and generics pretty much put a bow on the problem by providing the situation where you can't be sure that the types you will be working with have any particular best approach for deep copies.
    My usual boring signature: Nothing

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width