Results 1 to 17 of 17

Thread: Best practice - custom classes and assignments

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Jul 2004
    Location
    Kansas, USA
    Posts
    352

    Best practice - custom classes and assignments

    I have just learned that using the = operator creates a reference to the original instance of the class rather than creating a copy. What I did to get around this is created a ShallowCopy function:

    Code:
    Imports System.ComponentModel
    
    <TypeConverter(GetType(ExpandableObjectConverter)), Serializable()>
    Public Class BoundingBox
    
        Public Sub New()
            LowerLeft = New Vertex
            UpperRight = New Vertex
        End Sub
        Public Property LowerLeft As Vertex
        Public Property UpperRight As Vertex
    
    
        Public Function ShallowCopy() As BoundingBox
            Dim tempBB As New BoundingBox
            With tempBB
                .LowerLeft = LowerLeft.ShallowCopy
                .UpperRight = UpperRight.ShallowCopy
            End With
            Return tempBB
        End Function
    
    End Class
    My question...What is best practice regarding custom classes and creating copies that do not refer to the original instance data?
    Thanks,
    Eric
    --------------------------------------------------------------------------------------------------------------------
    VB.net/C# ... Visual Studio 2019
    "None of us are as smart as all of us."

  2. #2
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,532

    Re: Best practice - custom classes and assignments

    Pretty much that. Usually it's called .Clone, but I prefer the name you gave as it's plain that it's a shallow copy and not a deep copy.

    Because every class is different and all cases are different, there's no one good way to do this sort of thing.

    -tg
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  3. #3
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Best practice - custom classes and assignments

    That's not a shallow copy though. That's a deep copy. A shallow copy is a new object with all the same property/field values as the original, i.e. any reference type properties/fields in the new object will refer to the same objects as the original. The fact that you are making copies of the Vertex objects as well means that you're creating a deep copy.

  4. #4
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Best practice - custom classes and assignments

    Another best practice:

    Professionals always put the parameter list on their method calls, even if the list is empty, to help distinguish method calls from properties:
    Code:
    ' Do this:
    left.ShallowCopy()
    
    ' Not this:
    left. ShallowCopy()
    I was about to argue with JMC that this is a shallow copy, because at first glance your code confused me and I thought I was looking at 2 property accesses, not 2 method calls.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  5. #5
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    Re: Best practice - custom classes and assignments

    I'm still not sure whether it is deep or shallow. If Vertex is a structure, then it is deep, but I'm not familiar with a structure called Vertex, and a quick Google didn't show anything obvious. There are several things called Vertex, so I don't know what that Vertex object is. If it's a class, then it isn't deep, but it isn't really shallow, either. You have a new object that would hold references to the same items found in some other object. So, two objects....entangled, which doesn't seem like what was desired. If Vertex is a structure, then all is well, it's just a deep copy.
    My usual boring signature: Nothing

  6. #6
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Best practice - custom classes and assignments

    Quote Originally Posted by Shaggy Hiker View Post
    I'm still not sure whether it is deep or shallow. If Vertex is a structure, then it is deep, but I'm not familiar with a structure called Vertex, and a quick Google didn't show anything obvious. There are several things called Vertex, so I don't know what that Vertex object is. If it's a class, then it isn't deep, but it isn't really shallow, either. You have a new object that would hold references to the same items found in some other object. So, two objects....entangled, which doesn't seem like what was desired. If Vertex is a structure, then all is well, it's just a deep copy.
    You have to take a walk to figure out why it's deep.

    ShallowCopy() does this:
    • Create a new instance of this class.
    • Call ShallowCopy() on the left.
    • Call ShallowCopy() on the right.

    So since ShallowCopy() creates a new instance, calling it on the left and right instances creates two new instances. Hence, it's named wrong.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  7. #7
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Best practice - custom classes and assignments

    Quote Originally Posted by Shaggy Hiker View Post
    If it's a class, then it isn't deep, but it isn't really shallow, either.
    It's either shallow or it's deep. There are no other options. A shallow copy is one where you create a new instance and then simply assign property/field values from the original to the copy. If you want to create an actual shallow copy then you should call MemberwiseClone. Anything else is a deep copy. It doesn't matter how deep the copy is; if it's not shallow then it's deep. In this case, the code that creates the copy of the BoundingBox class doesn't simply assign LowerLeft and UpperRight property values of the original to the copy. It creates a (seemingly shallow, but maybe not) copy of the Vertex objects from the original and assigns those to the properties of the copy, thus the copy of the BoundingBox class is deep.

  8. #8
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Best practice - custom classes and assignments

    Quote Originally Posted by jmcilhinney View Post
    It's either shallow or it's deep. There are no other options.
    Actually there's a third option where you do some shallow work and some deep work Why? Generally by mistake.

    If you want to create an actual shallow copy then you should call MemberwiseClone.
    In general you want to write your own cloning code. Reflection-based copying of values is slower than direct assignments, and the performance burden can really add up. This is part of why the rules for creating structs very strongly recommend keeping them small, because all the automatic copy-by-values they can incur can be a problem. That's the reason why reference semantics exist at all!
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  9. #9
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    Re: Best practice - custom classes and assignments

    Quote Originally Posted by Sitten Spynne View Post
    Actually there's a third option where you do some shallow work and some deep work Why? Generally by mistake.
    That was what I was getting at. After all, it doesn't really matter what we call it, what matters is whether what is happening is what the OP wants to have happen. I assumed that at the end of the call, the OP expected to have a new object that was of the same type as the original, had the same values, but always had copies of the values, without any shared references between them. Depending on what Vertex is, and what they actually want the result to be, I'm not sure they are getting from that function what they want to get from the function.
    My usual boring signature: Nothing

  10. #10
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Best practice - custom classes and assignments

    Quote Originally Posted by Sitten Spynne View Post
    Actually there's a third option where you do some shallow work and some deep work
    The way I've read it, a shallow copy is one where all property/field values are assigned directly from the old to the new and a deep copy is anything else. What you're describing as a combination of the two is actually still a deep copy. Any depth anywhere makes it deep. How deep and how widespread that depth is irrelevant to that classification.

  11. #11
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    38,989

    Re: Best practice - custom classes and assignments

    I have always thought that a shallow copy was just a copy of the reference. Anything beyond that is some form of deep copy, and since it can take on just about any form, that is the reason why no standard deep copy of reference types is possible.
    My usual boring signature: Nothing

  12. #12
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Best practice - custom classes and assignments

    Quote Originally Posted by jmcilhinney View Post
    The way I've read it, a shallow copy is one where all property/field values are assigned directly from the old to the new and a deep copy is anything else. What you're describing as a combination of the two is actually still a deep copy. Any depth anywhere makes it deep. How deep and how widespread that depth is irrelevant to that classification.
    That makes the definition of "deep copy" worthless, IMO, but you're probably right because what I remember of the commentary about ICloneable is, "We can't get anyone to agree on what the definition of 'clone' means so we wish we hadn't added this interface at all and our internal guideline became "don't use it"."
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  13. #13
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Best practice - custom classes and assignments

    Quote Originally Posted by Sitten Spynne View Post
    That makes the definition of "deep copy" worthless, IMO
    I hear what you're saying, but I'm not sure that I agree. If "deep copy" meant something more specific than "a copy that isn't shallow" then we'd still need other names for the rest of the things that "deep copy" currently covers. If a deep copy was, by definition, a copy where each property/field value was copied then we'd still need another name/description for a copy where some property/field values were copied and others were assigned directly. We'd also need another name where some or all of the property/field values were themselves not shallow copies. Personally, I would say that it's just as easy to know that a shallow copy means that no reference property/field values are duplicated and a deep copy means that at least one is and if you care which are then it's up to you to check to find out.

  14. #14
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Best practice - custom classes and assignments

    What I mean is I want three definitions:
    • Shallow copy: reuses references thus changes in referenced things will impact both copies.
    • Deep copy: new instances of everything so no changes to either copy will affect the other.
    • Copy: Check the documentation for semantics.

    I don't have a use for words with adjectives in front of them if the adjectives don't imply something different from when the word had no adjectives.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  15. #15
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Best practice - custom classes and assignments

    Quote Originally Posted by Sitten Spynne View Post
    Deep copy: new instances of everything so no changes to either copy will affect the other.
    Would that distinguish between deep copies where the new instances were shallow copies and deep copies where the new instances were deep copies?

  16. #16
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    Re: Best practice - custom classes and assignments

    I was going to vehemently disagree but I came up with an example where you win.

    In the contexts I'm used to discussing this, safe concurrency is the concern. If I'm trying to make a copy of an object graph so I can give it to another thread and I don't want it to be able to mess up my original, I have to go out of my way to make sure the graphs of object A and object A' have no overlap. That's what I mean when I ask for a deep copy, and if I get anything less the copy isn't sufficient for my needs.

    But when I talked about an example, I realized it's less important that "every object instance is a new copy" and more important that "I can't change the clone in a way that impacts the parent". If we have immutable reference members, what was once a shallow copy becomes deep.

    Imagine "clone a button" meaning, for efficiency, something less than a deep clone. Obviously we need to call CreateWindow() and get a new hWnd. Various properties like size and location are going to be copies from being value types. But what about, say, the Font? Deep down, that's another thing with a handle, so if I don't intend on changing anything about it I probably don't want to create a new instance.

    But it turns out if I want to change anything, I have to create a new instance anyway, because Font is immutable. I think they did this to save you from the disaster that might happen if you grab, say, the system default Font and try to change something about it. Anyway, the point is even if A and A' share the same reference to a single Font object, there's no way I can change the font of A' in a way that affects A. So that copy becomes "deep enough", and the nitpick that I didn't recreate the Font object is irrelevant.

    Still, if we're talking about mutable reference members, the only way to satisfy the requirement of "deep copy" is to deep clone those. There's a lot of reasons why we're desperately trying to get syntax sugars for immutable "record types" in C#. It helps us get things done faster and safer.
    This answer is wrong. You should be using TableAdapter and Dictionaries instead.

  17. #17
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,299

    Re: Best practice - custom classes and assignments

    I think that, regardless of the labels used, the takeaway is that cloning/copying is not a straightforward proposition and you should always have your wits about you, whether you're doing the implementing or using someone else's implementation. I think that we probably agree on that, even if the detail of the labelling may be a minor point of contention.

    I think that another thing we agree on is that a shallow copy definitely is something specific and the example used in this thread appears not to satisfy the requirements of a shallow copy.

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