How to Clone Objects

C#Object

C# Problem Overview


When I do the following.. anything done to Person b modifies Person a (I thought doing this would clone Person b from Person a). I also have NO idea if changing Person a will change Person b after the linking. Due to my code right now, I can only see this in 1 direction.

Person a = new Person() { head = "big", feet = "small" };
Person b = a; 

b.head = "small"; //now a.head = "small" too   

Now if I do this instead.. Person a becomes completely separate.

Person b = new Person() { head = a.head, feet = a.feet };

Now this fine and kinda makes sense when comparing this behaviour to other things in C#. BUT, this could get very annoying with large objects.

Is there a way to shortcut this at all?

Such as:

Person b = a.Values;

C# Solutions


Solution 1 - C#

What you are looking is for a Cloning. You will need to Implement IClonable and then do the Cloning.

Example:

class Person() : ICloneable
{
    public string head;
    public string feet; 

    #region ICloneable Members

    public object Clone()
    {
        return this.MemberwiseClone();
    }

    #endregion
}

Then You can simply call the Clone method to do a ShallowCopy (In this particular Case also a DeepCopy)

Person a = new Person() { head = "big", feet = "small" };
Person b = (Person) a.Clone();  

You can use the MemberwiseClone method of the Object class to do the cloning.

Solution 2 - C#

> Is there a way to shortcut this at all?

No, not really. You'll need to make a new instance in order to avoid the original from affecting the "copy". There are a couple of options for this:

  1. If your type is a struct, not a class, it will be copied by value (instead of just copying the reference to the instance). This will give it the semantics you're describing, but has many other side effects that tend to be less than desirable, and is not recommended for any mutable type (which this obviously is, or this wouldn't be an issue!)

  2. Implement a "cloning" mechanism on your types. This can be ICloneable or even just a constructor that takes an instance and copies values from it.

  3. Use reflection, MemberwiseClone, or similar to copy all values across, so you don't have to write the code to do this. This has potential problems, especially if you have fields containing non-simple types.

Solution 3 - C#

I use AutoMapper for this. It works like this:

Mapper.CreateMap(typeof(Person), typeof(Person));
Mapper.Map(a, b);

Now person a has all the properties of person b.

As an aside, AutoMapper works for differing objects as well. For more information, check it out at http://automapper.org

Update: I use this syntax now (simplistically - really the CreateMaps are in AutoMapper profiles):

Mapper.CreateMap<Person, Person>;
Mapper.Map(a, b);

Note that you don't have to do a CreateMap to map one object of the same type to another, but if you don't, AutoMapper will create a shallow copy, meaning to the lay man that if you change one object, the other changes also.

Solution 4 - C#

Since the MemberwiseClone() method is not public, I created this simple extension method in order to make it easier to clone objects:

public static T Clone<T>(this T obj)
{
    var inst = obj.GetType().GetMethod("MemberwiseClone", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

    return (T)inst?.Invoke(obj, null);
}

Usage:

var clone = myObject.Clone();

Solution 5 - C#

To clone your class object you can use the Object.MemberwiseClone method,

just add this function to your class :

public class yourClass
{
    // ...
    // ...

    public yourClass DeepCopy()
    {
        yourClass othercopy = (yourClass)this.MemberwiseClone();
        return othercopy;
    }
}

then to perform a deep independent copy, just call the DeepCopy method:

yourClass newLine = oldLine.DeepCopy();

Solution 6 - C#

a and b are just two references to the same Person object. They both essentially hold the address of the Person.

There is a ICloneable interface, though relatively few classes support it. With this, you would write:

Person b = a.Clone();

Then, b would be an entirely separate Person.

You could also implement a copy constructor:

public Person(Person src)
{
  // ... 
}

There is no built-in way to copy all the fields. You can do it through reflection, but there would be a performance penalty.

Solution 7 - C#

It couldn't be simpler than this:

	public SomeClass Clone () {

		var clonedJson = JsonConvert.SerializeObject (this);

		return JsonConvert.DeserializeObject<SomeClass> (clonedJson);
	}

Just serialize any object to a JSON string and then deserialize it. This will do a deep copy...

Solution 8 - C#

MemberwiseClone is a good way to do a shallow copy as others have suggested. It is protected however, so if you want to use it without changing the class, you have to access it via reflection. Reflection however is slow. So if you are planning to clone a lot of objects it might be worthwhile to cache the result:

public static class CloneUtil<T>
{
    private static readonly Func<T, object> clone;

    static CloneUtil()
    {
        var cloneMethod = typeof(T).GetMethod("MemberwiseClone", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        clone = (Func<T, object>)cloneMethod.CreateDelegate(typeof(Func<T, object>));
    }

    public static T ShallowClone(T obj) => (T)clone(obj);
}

public static class CloneUtil
{
    public static T ShallowClone<T>(this T obj) => CloneUtil<T>.ShallowClone(obj);
}

You can call it like this:

Person b = a.ShallowClone();

Solution 9 - C#

Painlessly: Using NClone library

Person a = new Person() { head = "big", feet = "small" };
Person b = Clone.ObjectGraph(a); 

Solution 10 - C#

You could do it like this:

var jss = new JavaScriptSerializer();
var b = jss.Deserialize<Person>(jss.Serialize(a));

For deep cloning you may want to take a look at this answer: https://stackoverflow.com/a/78612/550975

Solution 11 - C#

  public static T Clone<T>(T obj)
  {
      DataContractSerializer dcSer = new  DataContractSerializer(obj.GetType());
      MemoryStream memoryStream = new MemoryStream();

      dcSer.WriteObject(memoryStream, obj);
      memoryStream.Position = 0;

      T newObject = (T)dcSer.ReadObject(memoryStream);
      return newObject;
  }

Solution 12 - C#

In my opinion, the best way to do this is by implementing your own Clone() method as shown below.

class Person
{
    public string head;
    public string feet;

    // Downside: It has to be manually implemented for every class
    public Person Clone()
    {
        return new Person() { head = this.head, feet = this.feet };
    }
}

class Program
{
    public static void Main(string[] args)
    {
        Person a = new Person() { head = "bigAF", feet = "smol" };
        Person b = a.Clone();

        b.head = "notEvenThatBigTBH";

        Console.WriteLine($"{a.head}, {a.feet}");
        Console.WriteLine($"{b.head}, {b.feet}");
    }
}

Output:

> bigAf, smol > > notEvenThatBigTBH, smol

b is totally independent to a, due to it not being a reference, but a clone.

Hope I could help!

Solution 13 - C#

This code worked for me. It also takes a very small amount of time to execute.

    public static void CopyTo(this object Source, object Destination)
    {
        foreach (var pS in Source.GetType().GetProperties())
        {
            foreach (var pT in Destination.GetType().GetProperties())
            {
                if (pT.Name != pS.Name) continue;
                (pT.GetSetMethod()).Invoke(Destination, new object[]
                { pS.GetGetMethod().Invoke( Source, null ) });
                break;
            }
        };
    }

Solution 14 - C#

private static readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true
};
public static T? FromJson<T>(this string json) => JsonSerializer.Deserialize<T>(json, _jsonOptions);
public static string ToJson<T>(this T obj) where T : class => JsonSerializer.Serialize(obj, _jsonOptions);
public static T? Clone<T>(this T obj) where T : class => obj.ToJson().FromJson<T>();

This is how I have solved it using the built in Json class and created some extension methods. These extension methods come in handy all over my project. (This is running on .NET 6)

Solution 15 - C#

This happens because "Person" is a class, so it is passed by reference. In the statement "b = a" you are just copying a reference to the one and only "Person" instance that you created with the keyword new.

The easiest way to have the behavior that you are looking for is to use a "value type".

Just change the Person declaration from

class Person

to

struct Person

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPiZzL3View Question on Stackoverflow
Solution 1 - C#Shekhar_ProView Answer on Stackoverflow
Solution 2 - C#Reed CopseyView Answer on Stackoverflow
Solution 3 - C#Kasey KrehbielView Answer on Stackoverflow
Solution 4 - C#tocquevilleView Answer on Stackoverflow
Solution 5 - C#Chtioui MalekView Answer on Stackoverflow
Solution 6 - C#Matthew FlaschenView Answer on Stackoverflow
Solution 7 - C#Steve MillerView Answer on Stackoverflow
Solution 8 - C#Tim PohlmannView Answer on Stackoverflow
Solution 9 - C#magallanesView Answer on Stackoverflow
Solution 10 - C#Serj SaganView Answer on Stackoverflow
Solution 11 - C#TatinfoView Answer on Stackoverflow
Solution 12 - C#WahooView Answer on Stackoverflow
Solution 13 - C#Kaizar Tariq InanView Answer on Stackoverflow
Solution 14 - C#JoshView Answer on Stackoverflow
Solution 15 - C#MaghisView Answer on Stackoverflow