Friday, 16 September 2011

C# Deep & Shallow Copy/Clone

class Program
{
  static void Main(string[] args)
  {
    var parent1 = new Parent() {Id = 1};
    parent1.Children = new List<Child>();
    parent1.Children.Add(new Child() { Name = "One" });
    parent1.Children.Add(new Child() { Name = "Two" });
    var parent2 = new Parent() { Id = 2 };
    parent2.Children = new List<Child>();
    parent2.Children.Add(new Child() { Name = "One" });
    parent2.Children.Add(new Child() { Name = "Two" });
    var parent3 = new Parent() { Id = 3 };
    parent3.Children = new List<Child>();
    parent3.Children.Add(new Child() { Name = "One" });
    parent3.Children.Add(new Child() { Name = "Two" });
    var parentShallowCopy = parent1.ShallowCopy();
    var parentDeepCopy = parent2.DeepCopy();
    var parentDeepClone = parent3.DeepClone();
    Console.WriteLine("ORIGINAL(1) : {0}", parent1);
    Console.WriteLine("SHALLOW COPY: {0}", parentShallowCopy);
    Console.WriteLine("ORIGINAL(2) : {0}", parent2);
    Console.WriteLine("DEEP COPY   : {0}", parentDeepCopy);
    Console.WriteLine("ORIGINAL(3) : {0}", parent3);
    Console.WriteLine("DEEP CLONE  : {0}", parentDeepClone);            
    parentShallowCopy.Children[0].Name = "Zero";
    parentDeepCopy.Children[0].Name = "Zero";
    parentDeepClone.Children[0].Name = "Zero";
    Console.WriteLine("");
    Console.WriteLine("ORIGINAL(1) : {0}", parent1);
    Console.WriteLine("SHALLOW COPY: {0}", parentShallowCopy);
    Console.WriteLine("ORIGINAL(2) : {0}", parent2);
    Console.WriteLine("DEEP COPY   : {0}", parentDeepCopy);
    Console.WriteLine("ORIGINAL(3) : {0}", parent3);
    Console.WriteLine("DEEP CLONE  : {0}", parentDeepClone); 
    Console.ReadLine();
  }
}
[Serializable]
class Parent
{
  public int Id { get; set; }
  public List<Child> Children { get; set; }
  public Parent ShallowCopy()
  {
    return (Parent)this.MemberwiseClone();
  }
  public Parent DeepCopy()
  {
    Parent other = (Parent)this.MemberwiseClone();
    other.Children = new List<Child>();
    this.Children.ForEach(x => other.Children.Add(x.DeepCopy()));            
    return other;
  }
  public override string ToString()
  {
    var sb = new StringBuilder();
    sb.AppendFormat("[Id:{0},Children:[", Id);
    Children.ForEach(x => sb.AppendFormat("{0},", x.ToString()));
    sb.Remove(sb.Length - 1, 1);
    sb.AppendFormat("]]");
    return sb.ToString();
  }
}
[Serializable]
class Child
{
  public string Name { get; set; }
  public override string ToString()
  {
    return string.Format("{0}", Name);
  }
  public Child ShallowCopy()
  {
    return (Child)this.MemberwiseClone();
  }
  public Child DeepCopy()
  {
    return (Child)this.MemberwiseClone();                        
  }
}
//extends classes that are marked [Serializable]
public static class ExtensionMethods
{        
  public static T DeepClone<T>(this T a)
  {
    using (MemoryStream stream = new MemoryStream())
    {
      BinaryFormatter formatter = new BinaryFormatter();
      formatter.Serialize(stream, a);
      stream.Position = 0;
      return (T)formatter.Deserialize(stream);
    }
  }
}

No comments:

Post a Comment