Object Copying in C#

When working on some sort of data-driven project, I frequently have the need to allow deep-copying of data objects. There are several patterns that accomplish this, but I’ve settled on one in particular.

Most .NET developers are probably familiar with the ICloneable interface. While this is a good starting point, it is not what I choose to rely on, for two reasons. First, the return type of the Clone method is object, so a cast is required. Second, the interface doesn’t really give you any special functionality. Nonetheless, implementing interfaces is usually a good thing, so my approach does use the interface, if only as a tag.

(I am leaving out equality test implementations for the sake of brevity, but one usually wants to implement equality testing when an object can be cloned.)

The common pattern I see when implementing a Clone method is to declare one public virtual method on the base class:

abstract class Animal
{
    public IList<Animal> Children { get; set; }

    public virtual Animal Clone()
    {
        var copy = (Animal)MemberwiseClone();

        // Deep-copy children
        copy.Children = Children.Select(c => c.Clone()).ToList();

        return copy;
    }
}

Simple enough. Let’s say that we have a derived class that needs some additional logic. We just override the Clone method, right?

class Dog : Animal
{
    public Collar Collar { get; set; }

    public virtual Animal Clone()
    {
        var copy = (Dog)base.Clone();

        copy.Collar = Collar.Clone();

        return copy;
    }
}

This works, but as soon as you try to clone a Dog directly, the ugliness of this pattern is apparent.

Animal animal = otherAnimal.Clone(); // Great!
Dog dog = otherDog.Clone();          // Compile-time error

Unfortunately, the return type of Animal.Clone() is Animal and subclasses may not change the return type, not even to narrow it. So to clone a Dog into a variable of type Dog means we have to cast:

Dog dog = (Dog)otherDog.Clone();

Yuck. This is passable, but it’s hardly optimal.

The good news is that with just one tweak, we can make this pleasant to deal with. First, the Clone method needs to be made protected and renamed. Second, we create a new public Clone method that is not virtual and calls the protected virtual method. Subclasses hide this method with a new implementation that does the same thing, but casts the result.

Here’s the full implementation:

abstract class Animal : ICloneable
{
    public IList<Animal> Children { get; set; }

    public Animal Clone()
    {
        return CloneImpl();
    }

    object ICloneable.Clone()
    {
        return CloneImpl();
    }

    protected virtual Animal CloneImpl()
    {
        var copy = (Animal)MemberwiseClone();

        // Deep-copy children
        copy.Children = Children.Select(c => c.Clone()).ToList();

        return copy;
    }
}

class Dog : Animal
{
    public Collar Collar { get; set; }

    new public Dog Clone()
    {
        return (Dog)CloneImpl();
    }

    protected virtual Animal CloneImpl()
    {
        var copy = (Dog)base.CloneImpl();

        copy.Collar = Collar.Clone();

        return copy;
    }
}

Now, we have nice class-specific methods that will return a properly-typed reference to the new copy.

Animal animal = otherAnimal.Clone(); // Works
Dog dog = otherDog.Clone();          // Also works!

It’s worth noting that both patterns will properly copy objects of more specific types than the reference you use to copy them. For example, given this variable:

Animal animal = new Dog();

animal.Clone() will return a Dog instance, typed as Animal. This is what we’d expect.

CategoriesC#

18 Replies to “Object Copying in C#”

  1. You could also just serialize the object to json and deserialize back using the class with json.net. Should be like 2 lines of code.

  2. @Josh: Fixed the formatting for you. Your suggestion would apply to these classes, but would require a similar pattern as I have proposed to deal with the typing problem. (If you implement ICloneable<Dog> on Dog you could not expose its Clone() method directly, as it would clash with the virtual Clone() defined on the superclass.) It’s a nice addition to my suggested pattern, but does not replace it.

    @Donny: You could, if you wanted to use a sledgehammer to kill a fly. I can’t imagine that using json.net to clone objects is going to be anywhere near as performant as MemberwiseClone(). (And having proper encapsulated deep-copying support is always a good thing. As the class author, you know what objects in your graph are mutable and need to be copied; json.net doesn’t, and will copy everything, whether or not it is necessary.)

    1. @Donny: I use JSON.NET myself, but for reading and writing JSON. 😉 Using it to copy objects seems like a misuse, and cannot possibly be regarded as efficient. Serialization is intended for data transmission and persistence. I’m sure it works, but there are lots of things that work that are regarded as bad practices.

  3. @Chris: Now just like everything it depends on the context of the situation. If your doing gaming, any type of graphics or math based programming, then yes you should n’t use this method.

  4. It would probably be a good idea to explicitly NOT implement IClonable, and also to call the method something else instead of Clone(). Using an interface implies that objects that implement the interface can be treated uniformly. The IClonable interface, however, doesn’t specify the behavior of the Clone() method (deep/versus shallow for instance). This means the interface doesn’t add any value, and widespread use will likely lead to flawed code later on (code that assumes ICloneables can be treated uniformly). Therefore, it’s better to avoid this interface completely.

  5. public static class CloneExtention
    {
            public static T Clone<T>(this T cloneable) where T : ICloneable
            {
                return (T)cloneable.Clone();
            }
    }

    and explicit ICloneable implementation, and Dog.Clone() would return instance of Dog

  6. @Donny – wow man, you made my day 🙂 Yes, I have seen people use these bizarre methods to make a copy … but this is simply unacceptable in a framework/library. You might use it as a dirty hack when your manager keeps threatening you if you don’t finish your task in time.

    @Denis – good idea, though extensions tend to “pollute” and also need to be explicitly added into scope.

  7. I’ve been doing something similar for some time:

    public interface ICopyable<T>
    {
    	T Copy();
    
    	void CopyTo(ref T target);
    }

    And derived classes are implemented like:

    public new SymbolContent Copy()
    {
    	var copy = new SymbolContent();
    	CopyTo(ref copy);
    	return copy;
    }
    
    public void CopyTo(ref SymbolContent target)
    {
    	var baseTarget = (Content) target;
    
    	CopyTo(ref baseTarget);
    
    	target.OriginId = OriginId;
    	target.SymbolCode = SymbolCode;
    	target.TimeAccessMode = TimeAccessMode;
    	target.Timestamp = Timestamp;
    }

    I like having a common interface being implemented, because it gives me ability to write extension methods, for example:

    public static class CopyableExtensions
    {
    	public static T LockAndCopy(this T instance) 
    		where T : ICopyable
    	{
    		lock (instance)
    		{
    			return instance.Copy();
    		}
    	}
    }
  8. IMHO, I think the code posted by Denis is much more compact and has the same level of usability as yours and type safety. It will also work seamlessly with value types. Good one, Denis!

    1. @Ananth: Assuming that you explicitly implement ICloneable, yes, it can be better. If ICloneable is not implemented or is implemented implicitly then this approach will not work.

      Were I going to use this method I would probably create a new interface (Oskar raised some good points that I did not consider previously), and name the interface method and the extension method differently to ensure that the extension can always be easily used, whether or not the interface is implemented implicitly.

      (OTOH, the extension may require a using statement in larger projects, while having a casting method in the class itself wouldn’t. It’s a trade-off.)

  9. Something that I didn’t state on my comment is that I never thought of using MemberwiseClone. It’s a good idea IF you remember to replace mutable object references with copies when doing a deep copy (shallow copying is a bad idea in a mutable environment).

    1. Agreed. I like the idea of having copy constructors, but they might lead to object slicing if one isn’t careful. For example, if B derives A and both have copy constructors, you could pass a B instance to A‘s copy constructor and wind up with a copy of a different type than the original. MemberwiseClone() ensures that you get an object of the exact same type, and each overload of the CloneImpl() method (in my pattern) should call the base method and then do whatever deep-copying is necessary for that specific class. The result is the ability to clone an object through a reference of type T, obtain a result typed as T, where the result will have the same actual type as the original object (T, or something more specific than T).

Comments are closed.