Thursday, April 29, 2010

Shallow copy and deep copy in .NET

A shallow copy creates a new instance of the same type as the original object, and then copies the nonstatic fields of the original object. If the field is a value type, a bit-by-bit copy of the field is performed. If the field is a reference type, the reference is copied but the referred object is not; therefore, the reference in the original object and the reference in the clone point to the same object.
Deep copies duplicate everything. A deep copy of a collection is two collections with all of the elements in the original collection duplicated. I mean a deep copy of an object duplicates everything directly or indirectly referenced by the fields in the object.

Well, sometimes definitions bring us to a uneasy situation where we found ourselves bit confused, puzzled and baffled. So need to get this concept step by step, I’m sure by this way we will be able to elaborate it more and more.

-Consider two objects, A and B, which each refer to two separate memory blocks.




For Shallow copy
While copying A into B, we are trying to attach B to the same memory block as A.




“Be careful while getting it, as we are copying A to B, I mean neither we are trying to copy the address nor we are in the process of paasing the reference.” Simply we are in the process of copying Object A’s data into B. This results in a situation in which some data is shared between A and B.

Thus modifying the one will alter the other. The original memory block of B is now no longer referred to from anywhere.



The advantage of shallow copies is that their execution speed is fast and does not depend on the size of the data.
For deep copy
In deep copy process as the data is actually copied over. So,




The result will have, A with original data in separate memory block (earlier) and B will have A’s duplicate data in separate memory block.



The advantage is that A and B do not depend's on each other but at the cost of a slower and more expensive copy.
Shallow Vs Deep Copy : Now for the implementation, let’s create a console application “ShallowVsDeepCopyPrj” and create two separate classes Product and ProductCatalog within that application, in both classes I have implemented ICloneable interface.

public class Product:ICloneable {

                  private String m_ProductName,m_ProductDesc;
                  private String prodName = "ABC of C#";
                  private ProductCatalog m_ProductCatalog = new ProductCatalog("ABC of C#", 
                  "AVAILABLE");

                  public Product() { this.Setm_ProductDesc="Test Your C# Skill";

                 this.Setm_ProductName = prodName; }
                 public String Setm_ProductDesc { set { m_ProductDesc = value; } get { return
                 m_ProductDesc; } }
                 public String Setm_ProductName { set { m_ProductName = value; } get { return
                 m_ProductName; } }
                public ProductCatalog Setm_ProductCatalog { set { m_ProductCatalog = value; } get { return  
                m_ProductCatalog; } }
                Object ICloneable.Clone() { return this.Clone(); }

                public virtual Product Clone() {
                          // Start with a flat, memberwise copy
                         Product shallowCopy_Prod = this.MemberwiseClone() as Product;
                         // Then shallow-copy everything that needs the- pecial attention
                         shallowCopy_Prod.Setm_ProductName = this.Setm_ProductName;
                         shallowCopy_Prod.Setm_ProductDesc = this.Setm_ProductDesc;
                         shallowCopy_Prod.Setm_ProductCatalog = this.Setm_ProductCatalog;
                         return shallowCopy_Prod; }         }

public class ProductCatalog : ICloneable {
                        private String m_ProductName, m_ProductStatus;
                        public ProductCatalog(string pName,string pCat) {
                                  this.Setm_ProductName = pName;
                                  this.Setm_ProductStatus = pCat; }

                       public String Setm_ProductStatus { set { m_ProductStatus = value; } get { return
                       m_ProductStatus; } }
                       public String Setm_ProductName { set { m_ProductName = value; } get { return
                       m_ProductName; } }

                      Object ICloneable.Clone() { return this.Clone(); }
                     
                      public virtual ProductCatalog Clone() {
                      // Start with a flat, memberwise copy
                     ProductCatalog deepCopy_ProdCat = this.MemberwiseClone() as ProductCatalog;
                     return deepCopy_ProdCat;     }
    }
-Now implementing these two class in main method like this

Product m_Product = new Product();  // Starts

try {
         Product cloneProd = (Product)m_Product.Clone();
         m_Product.Setm_ProductCatalog.Setm_ProductName = "Know The Facts - FIJ";
         m_Product.Setm_ProductCatalog.Setm_ProductStatus = "NOT AVAILABLE";

        Console.WriteLine("Source - Object A --" + m_Product.Setm_ProductName +
                      "--" + m_Product.Setm_ProductDesc + "--" +
                      m_Product.Setm_ProductCatalog.Setm_ProductName + "--" +
                      m_Product.Setm_ProductCatalog.Setm_ProductStatus);

       Console.WriteLine("Destination - Object B --" +
                    cloneProd.Setm_ProductName + "--" + cloneProd.Setm_ProductDesc + "--" +
                    cloneProd.Setm_ProductCatalog.Setm_ProductName + "--" +
                    cloneProd.Setm_ProductCatalog.Setm_ProductStatus);

} catch (Exception ex) {
                   Console.WriteLine(ex.Message.ToString()); }
Console.ReadLine();    //Ends
Will bring you output:
Source-Object A --ABC of C#--Test Your C# Skill--Know The Facts - FIJ--NOT AVAILABLE
Destination-Object B --ABC of C#--Test Your C# Skill--Know The Facts - FIJ--NOT AVAILABLE

As we tried to copy the object A’s data into object B by shallow copy process. It means change in any object will be reflected both places, and the same thing you can see in text “Know The Facts - FIJ--NOT AVAILABLE” part in source and Destination object.Now for deep copy approach simply we need to replace public virtual Product Clone() method by
public virtual Product Clone() {

          // Start with a flat, memberwise copy
          Product deepCopy_Prod = this.MemberwiseClone() as Product;
          // Then deep-copy everything that needs the - special attention
         deepCopy_Prod.Setm_ProductName = this.Setm_ProductName;
         deepCopy_Prod.Setm_ProductDesc = this.Setm_ProductDesc;
         deepCopy_Prod.Setm_ProductCatalog = this.Setm_ProductCatalog.Clone();
         return deepCopy_Prod; }

And after executing modified code, Output will be
Source-Object A--ABC of C#--Test Your C# Skill--Know The Facts - FIJ--NOT AVAILABLE
Destination - Object B --ABC of C#--Test Your C# Skill--ABC of C#--AVAILABLE

By analysing red font we can say that change's in one object will not alter another one as it is a deep copy.
Well,It was a simple story about shallow and deep copy.......enjoy coding

No comments:

Post a Comment