Click here to Skip to main content
15,883,901 members
Please Sign up or sign in to vote.
4.50/5 (2 votes)
See more:
Suppose that I have a button called button1, it has its own properties, events ... Now if I declare a new button called button2, the assignment button2 = button1 only means button2 and button1 refer to the same object, so changing any properties of either of them will reflect to the other. But that is not all you can think of. How do you do to make the button2 a copy of the button1, they are the same in properties, events ... but they don't refer to the same object. If the button1 had only one property "Location", the copying would be so easy with only one assignment button2.Location = button1.Location. But in fact, we can be in cases that the button1 has too many properties, events ... to copy and the copying each one by one will need much effort. So how can we do that easily in such cases?
Could you please help me solve this? I think the assignment between objects in C# is very necessary to work that way (do a reference) but sometimes we may need copy the values only!
Thank you so much!
Posted

It is called Cloning: as usual, MSDN and Google to the rescue! How to: Write a Copy Constructor (C# Programming Guide)[^]
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 8-May-11 15:33pm    
Correct, my 5. However, there are some more to it.

Now, I provided description of 3 different approaches, please see my answer.
--SA
[no name] 8-May-11 22:47pm    
Thank you so much!!!
What you're referring to is called cloning. There are few things to it.

First, if you simply copy an instance of one reference type to another instance, you have the reference to the same object, but if you copy an instance of value object you always got a shallow copy of the original object. If all instance members of the structure are also value objects and those value objects also have only value-type members, and so on, to the very bottom if it, you always have a full clone, but is a reference-type member is involved, you have a shallow copy: the reference-type components are not cloned but share the same references.

There is no one universal method of making a full clone of all members, recursively. One reason for that is that the infinite recursion should be avoided. The way to solve this problem is providing the custom cloning in your code.

The interface System.IsClonable is available exactly for this purpose. You can implement it for any type you want to clone (it could be a value type as well, a structure). You implement System.IsClonable.Clone and provide per-member cloning, re-creating and cloning each member (but perhaps not every one; it depends on your semantics) appropriately.

It does not guarantee full recursive cloning, as every member type can be a structure or a class encapsulating a mixture of reference and value type. These type may or may not implement the interface System.IsClonable. This is only a tool to guarantee custom cloning which may or may not be recursively complete.

However, I used to provide automatic fully automated recursive cloning as well. To do that, I introduced analogous interface IDeeplyClonable with default implementation based on Reflection. This implementation analyzes all members of the type and see if some of them of 1) value types, 2) implement IDeeplyClonable, 3) implement IClonable; depending on that, either a shallow copy or a method Clone is invoked for cloning a member. This approach should be used with care. It should guarantee recursive cloning does not go into infinite recursion; also it can be relatively slow.

There is one more exotic but comprehensive way to provide semantically complete cloning. Is is based on serialization, in particular in Data Contract. The cloning semantic will be based on DataContract/DataMember attributes applied to all types and members involved. The problem of infinite recursion can be solved automatically — this method allows persisting object graph even if it is not a tree (that is, even if it contains loops). This method is also the least intrusive (you only add attributes, do not touch and existing declarations). One can persist an object graph to memory stream (for example) and read id into another object which becomes and exact clone semantically fully equivalent to the original one. For big objects or object graphs, performance can be some minor problem, but it can be considered as a fair price for extreme consistency and robustness.

For further detail, see:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx[^],
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx[^],
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.aspx[^].

For overview, see http://msdn.microsoft.com/en-us/library/ms733127.aspx[^], only remember that your goal is not persistence per se, but in this case just deep cloning.

—SA
 
Share this answer
 
v3
Comments
Prasanta_Prince 8-May-11 21:25pm    
Good One SA..
Sergey Alexandrovich Kryukov 8-May-11 21:56pm    
Thank you, Prasanta.
--SA
[no name] 8-May-11 22:48pm    
Thank you SA so much, Wow I didn't think it's such a complex work! I'll try to understand and apply it in my projects!
Sergey Alexandrovich Kryukov 8-May-11 22:53pm    
You're welcome.
It is not so complex in real life; I just tried to describe most general case and 3 approached. Some special cases would be extremely simple.
Follow-up questions are welcome.
Cheers,
--SA
[no name] 8-May-11 22:51pm    
Oh, I mean "I didn't think" not "I don't think" , just for my bad English!
Thanks again!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900