The document discusses object cloning in C# programming. It explains shallow cloning versus deep cloning and demonstrates different approaches to cloning objects, including using the ICloneable interface and MemberwiseClone() method. It notes issues with these approaches. The fastest way to do a deep clone, it states, is to serialize an object to a stream and then deserialize it back, which performs a full deep copy. Code is provided to implement this serialization/deserialization cloning approach.
18. Cloning Objects
• ICloneable interface
• Another disadvantage of ICloneable is that the Clone method returns an object,
hence every Clone call requires a cast:
public interface ICloneable
{
object Clone();
}
Person joe = new Person();
joe.Name = "Joe Smith";
Person joeClone = (Person)joe.Clone();
19. namespace ConsoleApplicationCourseTest
{
class MainClass
{
public class Person : ICloneable
{
public string Name;
object ICloneable.Clone()
{
return this.Clone();
}
public Person Clone()
{
return (Person)this.MemberwiseClone();
}
}
public static void Main(String[] args)
{
Person joe = new Person();
joe.Name = "Joe Smith";
Person bob = (Person)joe.Clone();
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
bob.Name = "Bob PopUp";
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
}
}
}
20. namespace ConsoleApplicationCourseTest
{
class MainClass
{
public class Person : ICloneable
{
public string Name;
object ICloneable.Clone()
{
return this.Clone();
}
public Person Clone()
{
return (Person)this.MemberwiseClone();
}
}
public static void Main(String[] args)
{
Person joe = new Person();
joe.Name = "Joe Smith";
Person bob = (Person)joe.Clone();
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
bob.Name = "Bob PopUp";
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
}
}
}
21. namespace ConsoleApplicationCourseTest
{
class MainClass
{
public class Person : ICloneable
{
public string Name;
object ICloneable.Clone()
{
return this.Clone();
}
public Person Clone()
{
return (Person)this.MemberwiseClone();
}
}
public static void Main(String[] args)
{
Person joe = new Person();
joe.Name = "Joe Smith";
Person bob = (Person)joe.Clone();
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
bob.Name = "Bob PopUp";
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
}
}
}
22. namespace ConsoleApplicationCourseTest
{
class MainClass
{
public class Person : ICloneable
{
public string Name;
object ICloneable.Clone()
{
return this.Clone();
}
public Person Clone()
{
return (Person)this.MemberwiseClone();
}
}
public static void Main(String[] args)
{
Person joe = new Person();
joe.Name = "Joe Smith";
Person bob = (Person)joe.Clone();
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
bob.Name = "Bob PopUp";
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
}
}
}
23. namespace ConsoleApplicationCourseTest
{
class MainClass
{
public class Person : ICloneable
{
public string Name;
object ICloneable.Clone()
{
return this.Clone();
}
public Person Clone()
{
return (Person)this.MemberwiseClone();
}
}
public static void Main(String[] args)
{
Person joe = new Person();
joe.Name = "Joe Smith";
Person bob = (Person)joe.Clone();
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
bob.Name = "Bob PopUp";
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
}
}
}
24. namespace ConsoleApplicationCourseTest
{
class MainClass
{
public class Person : ICloneable
{
public string Name;
object ICloneable.Clone()
{
return this.Clone();
}
public Person Clone()
{
return (Person)this.MemberwiseClone();
}
}
public static void Main(String[] args)
{
Person joe = new Person();
joe.Name = "Joe Smith";
Person bob = (Person)joe.Clone();
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
bob.Name = "Bob PopUp";
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
}
}
}
25. namespace ConsoleApplicationCourseTest
{
class MainClass
{
public class Person : ICloneable
{
public string Name;
object ICloneable.Clone()
{
return this.Clone();
}
public Person Clone()
{
return (Person)this.MemberwiseClone();
}
}
public static void Main(String[] args)
{
Person joe = new Person();
joe.Name = "Joe Smith";
Person bob = (Person)joe.Clone();
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
bob.Name = "Bob PopUp";
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
}
}
}
joe FullName: Joe Smith
bob FullName: Joe Smith
joe FullName: Joe Smith
bob FullName: Bob PopUp
Press any key to continue...
26. namespace ConsoleApplicationCourseTest
{
class MainClass
{
public class Person : ICloneable
{
public string Name;
object ICloneable.Clone()
{
return this.Clone();
}
public Person Clone()
{
return (Person)this.MemberwiseClone();
}
}
public static void Main(String[] args)
{
Person joe = new Person();
joe.Name = "Joe Smith";
Person bob = (Person)joe.Clone();
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
bob.Name = "Bob PopUp";
Console.WriteLine("joe FullName: {0} nbob FullName: {1}", joe.Name, bob.Name);
}
}
}
joe FullName: Joe Smith
bob FullName: Joe Smith
joe FullName: Joe Smith
bob FullName: Bob PopUp
Press any key to continue...
31. public static class ObjectCopier
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
32. public static class ObjectCopier
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
33. public static class ObjectCopier
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
34. public static class ObjectCopier
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
35. public static class ObjectCopier
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
36. public static class ObjectCopier
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
37. End of Course
Go and have some fun and come back for the next
Advanced C# Course
38. Take a Look on my other courses
@ http://www.slideshare.net/ZGTRZGTR
Available courses to the date of this slide: