You can deep clone or copy objects in C# so that changes made to the new object do not affect the original object. In this post, we’ll show you a handful of ways to do this.
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
public class Person {
public string Name { get; set; }
public int Age { get; set; }
}
class Program {
static void Main(string[] args) {
Person original = new Person { Name = "John", Age = 30 };
// Create a new stream to serialize the object
MemoryStream stream = new MemoryStream();
// Create a BinaryFormatter object to serialize the object to the stream
BinaryFormatter formatter = new BinaryFormatter();
// Serialize the object to the stream
formatter.Serialize(stream, original);
// Reset the stream position to the beginning
stream.Position = 0;
// Deserialize the object from the stream
Person clone = (Person)formatter.Deserialize(stream);
// Change the name of the cloned object
clone.Name = "Jane";
// The original object remains unchanged
Console.WriteLine("Original: Name={0}, Age={1}", original.Name, original.Age);
Console.WriteLine("Clone: Name={0}, Age={1}", clone.Name, clone.Age);
}
}
In this example, we have a Person
class with Name
and Age
properties. We create an instance of this class and set its Name
and Age
properties to “John” and 30, respectively.
We then create a new MemoryStream
object and a BinaryFormatter
object to serialize the Person
object to the stream. After serializing the object, we reset the stream position to the beginning and deserialize the object to create a clone of the original object.
We then change the Name
property of the cloned object to “Jane”, while leaving the original object unchanged. Finally, we print out the Name
and Age
properties of both objects to show that the original object remains unchanged.
Note that in order for this deep cloning process to work, the class being cloned must be marked as [Serializable]
. Additionally, any classes that are referenced by the class being cloned must also be marked as [Serializable]
.
You can create a copy constructor for your class that takes an instance of the same class and copies the values of all properties and fields from the source object to the new object. Here’s an example:
public class Person {
public string Name { get; set; }
public int Age { get; set; }
public Person(Person other) {
this.Name = other.Name;
this.Age = other.Age;
}
}
To create a deep copy of a Person
object using the copy constructor, you can simply pass the original object as a parameter:
Person original = new Person { Name = "John", Age = 30 };
Person clone = new Person(original);
Instead of using the default serialization process, you can implement a custom serialization surrogate that creates a deep copy of the object. Here’s an example:
using System.Runtime.Serialization;
public class Person {
public string Name { get; set; }
public int Age { get; set; }
}
public class PersonSurrogate : ISerializationSurrogate {
public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) {
Person person = (Person)obj;
info.AddValue("Name", person.Name);
info.AddValue("Age", person.Age);
}
public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector) {
Person person = (Person)obj;
person.Name = info.GetString("Name");
person.Age = info.GetInt32("Age");
return person;
}
}
To use the surrogate, you need to create a new BinaryFormatter
object and set its SurrogateSelector
property to an instance of a SurrogateSelector
object that has registered the PersonSurrogate
object as a surrogate for the Person
class:
Person original = new Person { Name = "John", Age = 30 };
BinaryFormatter formatter = new BinaryFormatter();
SurrogateSelector selector = new SurrogateSelector();
selector.AddSurrogate(typeof(Person), new StreamingContext(StreamingContextStates.All), new PersonSurrogate());
formatter.SurrogateSelector = selector;
MemoryStream stream = new MemoryStream();
formatter.Serialize(stream, original);
stream.Position = 0;
Person clone = (Person)formatter.Deserialize(stream);
These are just a few examples of how you can deep clone objects in C#. The best approach depends on the specific requirements of your application.