Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. copy constructor needed?

copy constructor needed?

Scheduled Pinned Locked Moved C#
csharpc++question
8 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    berndg
    wrote on last edited by
    #1

    Recent convert from C++. Coding in C#, do I need defining copy constructors? The documentation to Object.MemberwiseClone() suggests the answer is No, but I'd be grateful for confirmation or correction. TIA, Bernd

    H 1 Reply Last reply
    0
    • B berndg

      Recent convert from C++. Coding in C#, do I need defining copy constructors? The documentation to Object.MemberwiseClone() suggests the answer is No, but I'd be grateful for confirmation or correction. TIA, Bernd

      H Offline
      H Offline
      Heath Stewart
      wrote on last edited by
      #2

      Short answer: it depends. First, there's nothing wrong with copy constructors. It's not commonly done in .NET because other, more common facilities exist (like implementing the ICloneable interface). This way, you can simply do MyObj o2 = (MyObj)o1.Clone(); (depending on whether you use a implicit or explicit interface declaration - something new to .NET). In your implementation of ICloneable.Clone, then, you can decide how to clone one object to another however you want. Object.MemberwiseClone(), however, does a shallow copy. What this means is that all intrinsic types (int, long, bool, etc.) are copied while all reference types (almost everything else) are merely referenced by the new object and, if you change a reference type in one object it will be changed in the other. A collection is a good example: if o1 has a collection and you use Object.MemberwiseClone, then o2 will have a reference to the same collection. If you add or remove a member of that collection in either object, it will be reflected in the other because it is the same collection. If you set the collection member to null in one object, however, the other object will still hold on to a reference of it, so if you use this approach, be sure to clean everything up properly. So, it really depends on your needs. Do you want the cloned object to have a shallow copy (i.e., a reference) of objects or a deep copy (i.e., completely different copy) where everything is a completely different object? If so, I would recommend implementing the ICloneable interface for consistency and better support, but there's nothing wrong with using a copy constructor - heck, if you want, do both! Just make use of the copy constructor in your implementation of ICloneable.

      -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

      A 1 Reply Last reply
      0
      • H Heath Stewart

        Short answer: it depends. First, there's nothing wrong with copy constructors. It's not commonly done in .NET because other, more common facilities exist (like implementing the ICloneable interface). This way, you can simply do MyObj o2 = (MyObj)o1.Clone(); (depending on whether you use a implicit or explicit interface declaration - something new to .NET). In your implementation of ICloneable.Clone, then, you can decide how to clone one object to another however you want. Object.MemberwiseClone(), however, does a shallow copy. What this means is that all intrinsic types (int, long, bool, etc.) are copied while all reference types (almost everything else) are merely referenced by the new object and, if you change a reference type in one object it will be changed in the other. A collection is a good example: if o1 has a collection and you use Object.MemberwiseClone, then o2 will have a reference to the same collection. If you add or remove a member of that collection in either object, it will be reflected in the other because it is the same collection. If you set the collection member to null in one object, however, the other object will still hold on to a reference of it, so if you use this approach, be sure to clean everything up properly. So, it really depends on your needs. Do you want the cloned object to have a shallow copy (i.e., a reference) of objects or a deep copy (i.e., completely different copy) where everything is a completely different object? If so, I would recommend implementing the ICloneable interface for consistency and better support, but there's nothing wrong with using a copy constructor - heck, if you want, do both! Just make use of the copy constructor in your implementation of ICloneable.

        -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

        A Offline
        A Offline
        Alvaro Mendez
        wrote on last edited by
        #3

        Great answer Heath (got my 5). Now, comparing these 2 lines:

        MyObj o2 = (MyObj)o1.Clone();
        MyObj o2 = new MyObj(o1);

        Syntactically I'd prefer to use the second line (with the copy ctor) to copy the object. It seems clearer -- you're creating a new object based on another one. So I ask, why bother with implementing ICloneable and overriding Clone and then having to cast the result? I guess I just don't understand what you mean by "consistency and better support" as the benefits. Do you have specific cases where implementing ICloneable is expected/required, such as for a collection class? Thanks, Alvaro


        Hey! It compiles! Ship it.

        H 1 Reply Last reply
        0
        • A Alvaro Mendez

          Great answer Heath (got my 5). Now, comparing these 2 lines:

          MyObj o2 = (MyObj)o1.Clone();
          MyObj o2 = new MyObj(o1);

          Syntactically I'd prefer to use the second line (with the copy ctor) to copy the object. It seems clearer -- you're creating a new object based on another one. So I ask, why bother with implementing ICloneable and overriding Clone and then having to cast the result? I guess I just don't understand what you mean by "consistency and better support" as the benefits. Do you have specific cases where implementing ICloneable is expected/required, such as for a collection class? Thanks, Alvaro


          Hey! It compiles! Ship it.

          H Offline
          H Offline
          Heath Stewart
          wrote on last edited by
          #4

          There's nothing wrong with either method, I just prefer implementing ICloneable because it's consistent with everything else in .NET and "Microsoft's way of doing things". ;P You can actually eliminate the need for a cast by having your own Clone() method and implementing ICloneable explicitly:

          public class MyClass : ICloneable
          {
          // ...
          public MyClass Clone()
          {
          // Create the clone and return.
          }
          object ICloneable.Clone()
          {
          return this.Clone();
          }
          }

          Explicit interfaces are great in many cases, especially when you have to define a method that is defined in an interface already, or implementing two or more interfaces that may have the same members. They also come in handy for typed expressions like above. Several of your ICollection implementations in the BCL do this very thing to, at the very least, give you the appearance of a typed return and to prevent you from having to cast. As I said, though, you could use both ways::

          public class MyClass : ICloneable
          {
          // ...
          public MyClass(MyClass orig)
          {
          // Create this clone from the original.
          }
          public MyClass Clone()
          {
          return new MyClass(this);
          }
          object ICloneable.Clone()
          {
          return this.Clone();
          }
          }

          You get the best of both worlds, then. Another reason, which I use in a complex and abstract tree "framework" in the app I architected for work, is for treating object instances depending on what they implement. While recursing through a tree during various operations (such as cloning a tree) I determine if the object (so remember, I have no idea if a copy constructor exists for the Type without using quite a bit of reflection and many extra calls) implements ICloneable. If it does, I clone it. If it doesn't, I use a tab bit of reflection to create a new instance and do a memberwise clone (shallow copy). Most of the objects in the tree implement ICloneable, so I don't revert to reflection often and will most likely remove that functionality in a future version. The tree objects facilitate cloning by checking certain member fields for cloneability and do things in a similar matter. This creates a large chunck of functionality that never has to deal with any specific types in either the base class or the various child classes for a very nice OO design. This is just one example where using the interface helps, but it's not required. It just depends on circumstan

          A 1 Reply Last reply
          0
          • H Heath Stewart

            There's nothing wrong with either method, I just prefer implementing ICloneable because it's consistent with everything else in .NET and "Microsoft's way of doing things". ;P You can actually eliminate the need for a cast by having your own Clone() method and implementing ICloneable explicitly:

            public class MyClass : ICloneable
            {
            // ...
            public MyClass Clone()
            {
            // Create the clone and return.
            }
            object ICloneable.Clone()
            {
            return this.Clone();
            }
            }

            Explicit interfaces are great in many cases, especially when you have to define a method that is defined in an interface already, or implementing two or more interfaces that may have the same members. They also come in handy for typed expressions like above. Several of your ICollection implementations in the BCL do this very thing to, at the very least, give you the appearance of a typed return and to prevent you from having to cast. As I said, though, you could use both ways::

            public class MyClass : ICloneable
            {
            // ...
            public MyClass(MyClass orig)
            {
            // Create this clone from the original.
            }
            public MyClass Clone()
            {
            return new MyClass(this);
            }
            object ICloneable.Clone()
            {
            return this.Clone();
            }
            }

            You get the best of both worlds, then. Another reason, which I use in a complex and abstract tree "framework" in the app I architected for work, is for treating object instances depending on what they implement. While recursing through a tree during various operations (such as cloning a tree) I determine if the object (so remember, I have no idea if a copy constructor exists for the Type without using quite a bit of reflection and many extra calls) implements ICloneable. If it does, I clone it. If it doesn't, I use a tab bit of reflection to create a new instance and do a memberwise clone (shallow copy). Most of the objects in the tree implement ICloneable, so I don't revert to reflection often and will most likely remove that functionality in a future version. The tree objects facilitate cloning by checking certain member fields for cloneability and do things in a similar matter. This creates a large chunck of functionality that never has to deal with any specific types in either the base class or the various child classes for a very nice OO design. This is just one example where using the interface helps, but it's not required. It just depends on circumstan

            A Offline
            A Offline
            Alvaro Mendez
            wrote on last edited by
            #5

            I'm a little alarmed about your ICloneable.Clone implementation. It just calls Clone, which would seem to indicate an endless recursive call to itself. Does putting this. in front of it tell the compiler to call the other version? So if I have,

            MyClass m1 = new MyClass();

            m1.Clone(); // 1
            object o = m1.Clone(); // 2
            MyClass m2 = (MyClass)m1.Clone(); // 3

            What does each call to Clone actually end up calling? Thanks, Alvaro


            Hey! It compiles! Ship it.

            H 1 Reply Last reply
            0
            • A Alvaro Mendez

              I'm a little alarmed about your ICloneable.Clone implementation. It just calls Clone, which would seem to indicate an endless recursive call to itself. Does putting this. in front of it tell the compiler to call the other version? So if I have,

              MyClass m1 = new MyClass();

              m1.Clone(); // 1
              object o = m1.Clone(); // 2
              MyClass m2 = (MyClass)m1.Clone(); // 3

              What does each call to Clone actually end up calling? Thanks, Alvaro


              Hey! It compiles! Ship it.

              H Offline
              H Offline
              Heath Stewart
              wrote on last edited by
              #6

              First of all, I always type the implicit this. to help distinguish what's an instance member and what's a variable, just like I type the class name even for static members. It's basically just a way I manage my code. It makes absolutely NO difference when it compiles. The IL instructions are the same in either case. Second, the seemingly self-recursive cloning: doesn't happen. Are you familiar with explicit interface implementations? Notice how I used the interface name in the last Clone method: object ICloneable.Clone()? That means that you must cast the object (or define the object reference as that interface) in order to call that particular method. In the explicit interface implementation, I called this.Clone(); which is the Clone method of my class. If I did ((ICloneable)this).Clone(), then that would definitely be a problem! That is not what I did, however. Trust me, it works. Try throwing together a quick class that does this. Compile it and examine the IL (don't decompile - the IL is what you want to look at for this): it should show you what's being done. You don't necessarily have to implement ICloneable as an explicit interface. I only did it because someone (might have been you - don't remember) complained that you have to cast the return value of Clone. By having another Clone method on your class that returns the proper type, you won't have to worry about it. Heck, you don't even need to implement ICloneable, but that may throw-off developers that are thinking that you implement ICloneable when, in fact, you don't (and they didn't read your documentation, which happens far too often than not).

              -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

              A 1 Reply Last reply
              0
              • H Heath Stewart

                First of all, I always type the implicit this. to help distinguish what's an instance member and what's a variable, just like I type the class name even for static members. It's basically just a way I manage my code. It makes absolutely NO difference when it compiles. The IL instructions are the same in either case. Second, the seemingly self-recursive cloning: doesn't happen. Are you familiar with explicit interface implementations? Notice how I used the interface name in the last Clone method: object ICloneable.Clone()? That means that you must cast the object (or define the object reference as that interface) in order to call that particular method. In the explicit interface implementation, I called this.Clone(); which is the Clone method of my class. If I did ((ICloneable)this).Clone(), then that would definitely be a problem! That is not what I did, however. Trust me, it works. Try throwing together a quick class that does this. Compile it and examine the IL (don't decompile - the IL is what you want to look at for this): it should show you what's being done. You don't necessarily have to implement ICloneable as an explicit interface. I only did it because someone (might have been you - don't remember) complained that you have to cast the return value of Clone. By having another Clone method on your class that returns the proper type, you won't have to worry about it. Heck, you don't even need to implement ICloneable, but that may throw-off developers that are thinking that you implement ICloneable when, in fact, you don't (and they didn't read your documentation, which happens far too often than not).

                -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

                A Offline
                A Offline
                Alvaro Mendez
                wrote on last edited by
                #7

                Thanks for the explanation. "Explicit interface implementation" is definitely cool. :cool: Heath Stewart wrote: First of all, I always type the implicit this. to help distinguish what's an instance member and what's a variable, just like I type the class name even for static members. Yes, I do the same for instance fields (well, in Java anyway; in .NET I use the m_ prefix for my fields.) But for instance methods I think this. is just overkill. Since global methods do not exist, it's clear that calling a method directly (without a something. in front it) means you're calling a member of the class. Regards, Alvaro


                Hey! It compiles! Ship it.

                H 1 Reply Last reply
                0
                • A Alvaro Mendez

                  Thanks for the explanation. "Explicit interface implementation" is definitely cool. :cool: Heath Stewart wrote: First of all, I always type the implicit this. to help distinguish what's an instance member and what's a variable, just like I type the class name even for static members. Yes, I do the same for instance fields (well, in Java anyway; in .NET I use the m_ prefix for my fields.) But for instance methods I think this. is just overkill. Since global methods do not exist, it's clear that calling a method directly (without a something. in front it) means you're calling a member of the class. Regards, Alvaro


                  Hey! It compiles! Ship it.

                  H Offline
                  H Offline
                  Heath Stewart
                  wrote on last edited by
                  #8

                  It's all a matter of personal preference. It certainly doesn't hurt anything (like I said, whether or not you use this, it compiles to the same IL instructions). I use it merely for code-readability...well, that I can type "this." faster than hitting Ctrl+J! :) While I think too many "developers" (see my personal message board for comments!) rely merely on IntelliSense for their stumbling around...er, coding...it the auto-complete does come in handy for coding faster and avoiding fewer spelling errors. Again, though, it's all a matter of personal preference. I know that this ( and Me, although I hate languages that "use me" :laugh: ) is implicit (heck, I've been doing this a very long time) but I just personally find it easier to see what's what as I'm flying through code. And, yes, explicit interfaces are definitely cool - sometimes even necessary (ex: interface member collisions). They can also help hide a lot of the implementation details and force developers using your library to treat your object as a specific interface rather than just your Type (hopefully forcing good OO development).

                  -----BEGIN GEEK CODE BLOCK----- Version: 3.21 GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++ -----END GEEK CODE BLOCK-----

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups