Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / All-Topics

4 Ways of Object Clone

5.00/5 (1 vote)
10 Feb 2014CPOL2 min read 12K  
Here are 4 ways of object clone

Introduction

We usually need to copy all contents of an instance to another which have the same object type (or heritage object). I know four ways to do that, some of them are good and some are bad.

Using the Code

  1. Copy all properties of the object to another. This is not a bad way. It clones properties’ value without creating a new instance. But if we have more than 200 properties in the object, you know what will happen to us.
    C#
    class ObjectA
    {
    	public string Property1 { get; set; }
    	public string Property2 { get; set; }
    	public string Property3 { get; set; }
    }
    
    class Run : IRun
    {
    	public void CopyFromSecondToFirst(ObjectA firstObj, ObjectA secondObj)
    	{
    		firstObj.Property1 = secondObj.Property1;
    		firstObj.Property2 = secondObj.Property2;
    		firstObj.Property3 = secondObj.Property3;
    	}
    }

    We could also encapsulate this way to a method of the Object A:

    C#
    class ObjectA
    {
    	public string Property1 { get; set; }
    	public string Property2 { get; set; }
    	public string Property3 { get; set; }
    
    	public virtual void CloneFrom(ObjectA obj)
    	{
    		this.Property1 = obj.Property1;
    		this.Property2 = obj.Property2;
    		this.Property3 = obj.Property3;
    	}
    }
  2. Copy all properties by using PropertyInfo. This is a reflection way. It’s a dynamic way, but it costs too much time to copy values.
    C#
    class Run : IRun
    {
    	public void CopyFromNewToOrigin(ObjectA originObj, ObjectA newObj)
    	{
    		PropertyInfo[] properties = typeof(ObjectA).GetType().GetProperties();
    		foreach (PropertyInfo prop in properties)
    		{
    			var value = properties.GetValue(newObj, null) as string;
    			originObj.SetValue(originObj, value, null);
    		}
    	}
    }
  3. MemberwiseClone() creates a shallow copy by creating a new object, and then copying the non-static fields of the current object to the new object. This method has almost the same performance as the first one, it means ten times faster than the reflection method. But it creates a new instance instead of just copying values of properties.
    C#
    class ObjectA : ICloneable
    {
    	public string Property1 { get; set; }
    	public string Property2 { get; set; }
    	public string Property3 { get; set; }
    
    	// This create a new instance
    	public object Clone()
    	{
    		return (ObjectA)this.MemberwiseClone();
    	}
    }

    In multi-thread UI development, this way is often used. But because it’s a shallow copy, if in the class ObjectA has a reference type property, this property’s reference is copied but the referred object is not, therefore the original object and its clone refer to the same object.

  4. MemberwiseClone is a shallow copy, we can create a deep copy based on this shallow copy method. Here is MSDN’s example of creating a deep copy:
    C#
    public class IdInfo
    {
        public int IdNumber;
    
        public IdInfo(int IdNumber)
        {
            this.IdNumber = IdNumber;
        }
    }
    
    public class Person 
    {
        public int Age;
        public string Name;
        public IdInfo IdInfo;
    
        public Person ShallowCopy()
        {
           return (Person)this.MemberwiseClone();
        }
    
        public Person DeepCopy()
        {
           Person other = (Person) this.MemberwiseClone(); 
           other.IdInfo = new IdInfo(this.IdInfo.IdNumber);
           return other;
        }
    }

    There are also other ways to have a deep copy. Shallow copy and deep copy are both well explained in the MSDN page: Object.MemberwiseClone Method.

    In 3′s shallow copy, class implemented System.ICloeanable. But MSDN remarked that: The ICloneable interface simply requires that your implementation of the Clone method return a copy of the current object instance. It does not specify whether the cloning operation performs a deep copy, a shallow copy, or something in between. Nor does it require all property values of the original instance to be copied to the new instance. For example, the NumberFormatInfo.Clone method performs a shallow copy of all properties except the NumberFormatInfo.IsReadOnly property; it always sets this property value to false in the cloned object. Because callers of Clone cannot depend on the method performing a predictable cloning operation, we recommend that ICloneable not be implemented in public APIs.

Points of Interest

Instead of my four ways of copying an object, there is also something like AutoMapper. Wish my tip helps you.

Please also give me some other suggestions about this subject. Thanks!

License

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