Creating a Copy of an Object in C#

Creating a copy of an object in C#

There is no built-in way. You can have MyClass implement the IClonable interface (but it is sort of deprecated) or just write your own Copy/Clone method. In either case you will have to write some code.

For big objects you could consider Serialization + Deserialization (through a MemoryStream), just to reuse existing code.

Whatever the method, think carefully about what "a copy" means exactly. How deep should it go, are there Id fields to be excepted etc.

Easy way to make a copy of a Type object

There will always be only one Type for each class, so you can safely assign it.

Excerpt from Object.GetType:

For two objects x and y that have identical runtime types, Object.ReferenceEquals(x.GetType(),y.GetType()) returns true.

So there is no way that two Type instances could exist for any given class, there will always be only one (ReferenceEquals cannot be overriden)

In your case you could just do:

copy.ConnectionType = ConnectionType;

Full example:

public class A
{
public int Quantity { get; set; } = 0;
public Type ConnectionType { get; set; } = null;
public A Copy()
{
var copy = new A();
copy.Quantity = Quantity;
copy.ConnectionType = ConnectionType;
return copy;
}
}

How do you do a deep copy of an object in .NET?

Important Note

BinaryFormatter has been deprecated, and will no longer be available in .NET after November 2023. See BinaryFormatter Obsoletion Strategy


I've seen a few different approaches to this, but I use a generic utility method as such:

public static T DeepClone<T>(this T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;

return (T) formatter.Deserialize(ms);
}
}

Notes:

  • Your class MUST be marked as [Serializable] for this to work.

  • Your source file must include the following code:

     using System.Runtime.Serialization.Formatters.Binary;
    using System.IO;

How do you make a copy of an object?

Create a copy constructor for Colors. Then, do this.

Colors objColors = new Colors((Colors)Session["Colors"]);

In your new constructor, just copy the values that you need to and do your other constructor-related things.

What's happening in your code is that you are getting a pointer to a Colors object. Session["Colors"] and objColors point to the same object in memory, so when you modify one, changes are reflected in both. You want a brand spankin' new Colors object, with values initialized from objColors or Session["Colors"].

edit: A copy constructor might look like this:

public Colors(Colors otherColors)
{
this.privateVar1 = otherColors.privateVar1;
this.publicVar2 = otherColors.publicVar2;
this.Init();
}

.NET Copy object to existing object

This is not really a recommended approach, as it won't work and could have unpredictable results for certain object types, e.g. classes that have private fields or other internal data structures that cannot be recreated by copying the publicly available properties.

That being said, it is pretty trivial to iterate through an arbitrary's object's properties (you could even use an anonymous type) and use them as data points to populate another object. This extension method should do it:

static class ExtensionMethods
{
static public void CopyTo(this object source, object destination)
{
var destinationType = destination.GetType();

foreach (var s in source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var d = destinationType.GetProperty(s.Name);
if (d == null) continue; //No matching property
if (!d.CanWrite) continue; //Property found, but is read only
if (!d.PropertyType.IsAssignableFrom(s.PropertyType)) continue; //properties are not type-compatible
d.SetValue(destination, s.GetValue(source));
}
}
}

Example:

public class Program
{
public static void Main()
{
List<Car> cars = new List<Car> { new Car(), new Car() };

var b = cars[0];

var a = new { Brand = "Something", Price = 123M}; //Notice this is an anonymous type. You can use any object, as long as the properties match.

a.CopyTo(cars[0]);

Console.WriteLine("Brand: {0}", cars[0].Brand);
Console.WriteLine("Price: {0}", cars[0].Price);
}
}

Output:

Brand: Something
Price: 123

See my code on DotNetFiddle



Related Topics



Leave a reply



Submit