Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Wednesday, March 16, 2011 6:29 AM
Hi,
I have a class with private variables, public properties and private/public member functions, etc.
I have created an instance of this class and did some manipulations on this object.
I want to create the Copy/Clone of this instance without having reference to the original object for some reason.
But the copied/cloned object should be exactly same as original object. All private variables, public variables, properties should have the same value as in Original Object.
Please help me how to do this?
Please let me what is the best way to Copy/Clone the object?
I need some experts help on this issue.
Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This will help other members to find the solution easily.
All replies (14)
Wednesday, March 16, 2011 6:36 AM
Hello,
The easiest and simplest mode to achieve this is to use ICloneable,
For an ICloneable implementation please take a look at this article , where you will find both cloning methods explained: shallow & deep.
Hope this helps, if you have any other questions or comments, please let me know,
Best Regards,
Emanuel Varga
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
Wednesday, March 16, 2011 6:44 AM
Hi Emanuel,
Thanks for your reply.
I have gone through lot of blogs.
In some places I read that It is not recommended to use I Clonable.
IClonable is deprecated (see both the .NET Framework Standard Library Annotated Reference and the Framework Design Guidelines both recommend not implementing ICloneable.) Just implement a Clone method.
Also I want to copy the values from the private variables also. Perfect Copy I mean
I really need to take decision and go ahead with my implementations.
So I want to hear it from someone who had real time experience on this.
Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This will help other members to find the solution easily.
Wednesday, March 16, 2011 6:49 AM
Hello again,
It does not really matter if you implement ICloneable, or create your own interface or just use a Clone() method, you can implement the entire cloning logic in that method. Please take a look at the article i've proposed in my previous answer.
Hope this helps, if you have any other questions or comments, please let me know,
Best Regards,
Emanuel Varga
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
Wednesday, March 16, 2011 7:28 AM
Hi,
Thanks for your reply again.
I have already done through this article. But again thanks for it also.
When i use that Closning mechanism whether my private variables in Copied/Cloned Object also will have the same value as like in Original Object?
Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This will help other members to find the solution easily.
Wednesday, March 16, 2011 7:32 AM
Hello again,
Yes, because you are implementing the logic behind the cloning mechanism, you should think of cloning, just like overriding the Equals method, you should create a new object, set all the required properties and fields, and return that object.
Hope this helps, if you have any other questions or comments, please let me know,
Best Regards,
Emanuel Varga
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
Wednesday, March 16, 2011 7:35 AM
A really good way to clone objects is to serialize/deserialize them with System.Xml.Serialization. One limitation is that all the "private fields" must be accessable via public properties.
There are some other deep clone methods around that use reflection, however, most that I have seen are not as complete as serialization.
If you don't have a need to "protect" your private fields and don't mind wrapping them in public properties then it could be as simple as marking up the object you want to clone as [Serializable] and using the XmlSerializer to serialze to Xml then deserialize back into a new object of your type.
hth;
jz
Wednesday, March 16, 2011 7:39 AM
Ksvimal,
Be aware that words as cloning and copy have different meanings in .Net.
Even a shallow copy (only copying the references) is in some places explained different.
For instance a clone of the dataset is only copying the properties, events and members which are added to the object which is created.
http://msdn.microsoft.com/en-us/library/system.data.dataset.clone.aspx
While in this case the copy is copying also the data and making therefore a so called deep copy.
http://msdn.microsoft.com/en-us/library/system.data.dataset.clone.aspx
With most classes the deep copy can only be done by serializing and deserializing the object.
So it is up to you what is the best way, but always read first the description of the class and its available methods.
Success
Cor
Wednesday, March 16, 2011 7:44 AM
See MemberWiseClone ...there's an example of its use at the link as well as some additional info which may be useful.
ShaneB
Wednesday, March 16, 2011 8:09 AM
Hi All,
Thanks for your reply.
I am already using XML Serialization to Clone the Object.
Please check the below sample.
Class Account : I_Account
{
... contains private variables, public properties, methods, etc...
}
I retrieve the data from the database and fill the each record into the each instance of this class object and added into the List<I_Account> object.
Now i want to clone this List<I_Account> object. Because my Datagrid is editable, if i click on cancel then Datagrid modificatyions should be rolled back.
This is my scenario.
I have the following problem in doing this.
1. I use private variables for internal calculation/logic which is not copied to the cloned object.
2. If the Class Account has any List with another class objects then I have to Clone that seperately. I am using XmlIgnore to ignore this object and cloning that again manually by following the same procedure.
3. Dictionary I cant use in the class. I have to use the SerializableDictionary.
4. Since I have to clone all the objects in the list it takes so much time. Sometimes I feel it is better to retrieve the data once again instead of cloning.
I appreciate if you can spend some time on this issue and provide some good solution/suggestion on this.
It will be helpful even for others also.
Thanks in advance!!!
Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This will help other members to find the solution easily.
Wednesday, March 16, 2011 8:17 AM
Hello again,
Serialization will always be slower than the option i have suggested, but if you want to improve on the speed, just use binary serialization , it's almost 10 times as fast as xml serialization.
Hope this helps, if you have any other questions or comments, please let me know,
Best Regards,
Emanuel Varga
If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
Friday, March 18, 2011 8:49 AM | 1 vote
Since this hasn't been marked as answered, I'd like to add a comment;
It sounds like what you are trying to achieve is the ability to create a clone of your object for the purpose of allowing edits to be reverted.
I'd like to point out that while cloning your dataobject seems like the most efficent way to go about this, the idea of one method call to provide you with a edit/cancel pattern is an over-simplification.
IMO, you are much better off building a "view" (viewobject) as a wrapper to your dataobject and manually writting code to propagate the relevant dataobject properties to the viewobject. The reason for this is it gives you a layer of abstraction in which to do validation/conversion as well as seperating concerns and decoupling.
My advice to you is don't let the tedium of writting "viewobject.PropertyX = dataobject.PropertyX" and vice-versa on commit, lead you down the path of limiting your ability to control your model. Ask yourself if avoiding the "manual" replication of properties is worth the headache of managing the reference state of your object graph.
Simply, in the time it has taken to post your thread, get responses and ask for refinement, you could have written a view model that would suit your needs far more perfectly than simply cloning your dataobject - I mean no offence or judgment tword your question, only pointing out what I think is a simple truth.
hth;
jz
Wednesday, February 13, 2013 1:44 PM
Hi, I have wrote a smat tutorial article on how to clone objects in c#.
I hope it will be helpful. http://pragmaticcoding.com/index.php/cloning-objects-in-c/
Friday, November 29, 2013 6:27 PM
public static object Clone(object obj)
{
object new_obj = Activator.CreateInstance(obj.GetType());
foreach (PropertyInfo pi in obj.GetType().GetProperties())
{
if (pi.CanRead && pi.CanWrite && pi.PropertyType.IsSerializable)
{
pi.SetValue(new_obj, pi.GetValue(obj, null), null);
}
}
return new_obj;
}
This example, you can adjust to your needs.
For example,
if (pi.PropertyType == typeof(string))
{
pi.SetValue(new_obj, pi.GetValue(obj, null), null);
}
OR
if (pi.PropertyType.IsEnum)
{
...;
}
Friday, November 29, 2013 9:36 PM
There is a pattern called "Copy Constructor" for cloning in C#:
http://msdn.microsoft.com/en-us/library/ms173116.aspx
What exactly is the class containing? Especially is it containing references to classes other then string? If yes, you have to take care to clone those too (deep cloning as opposed to shallow cloning).
Value Types, stucts and String (because it is inmutable) don't need any extra care when cloning. But arrays of any type and each class other then string generally do.
Let's talk about MVVM: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b1a8bf14-4acd-4d77-9df8-bdb95b02dbe2 Please mark post as helpfull and answers respectively.