C# – How to Clone an Inherited Object

c++cloning

I've got a Tile class with this method:

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

And another class Checker that inherits from Tile.

I also have a Board class that is a List<Tile>. I want to clone the board, so I wrote this:

    public Board Clone()
    {
        var b = new Board(width, height);
        foreach (var t in this) b.Add(t.Clone());
        return b;
    }

But it throws an error:

cannot convert from 'object' to 'Checkers.Tile'

Now I can make the Tile.Clone method return a Tile instead, but then will the MemberwiseClone copy the additional properties in the sub-Checker as well?


If that's not the problem, what's the semantic difference between the above Board.Clone method and this?

    public Board Clone()
    {
        using (var ms = new MemoryStream())
        {
            var bf = new BinaryFormatter();
            bf.Serialize(ms, this);
            ms.Position = 0;
            return (Board)bf.Deserialize(ms);
        }
    }

Because they're definitely having different effects on my program, even though when I print the board it looks the same. I don't think something is being cloned but a reference is being returned. The Board ctor looks like this:

    public Board(int width = 8, int height = 8)
    {
        this.width = width;
        this.height = height;
        this.rowWidth = width / 2;
        this.Capacity = rowWidth * height;
    }

The Tile class actually doesn't have any properties. The checker just has two enums properties:

public enum Color { Black, White };
public enum Class { Man, King };

public class Checker : Tile
{
    public Color Color { get; set; }
    public Class Class { get; set; }

Best Answer

Yes, MemberwiseClone will also copy the Checker-only fields. MemberwiseClone cannot know the return type of your Clone method; therefore, it's behaviour cannot depend on it.


About the difference betweeen your Clone implementation and the serialization: MemberwiseClone creates a shallow copy of the Tiles: If a Tile (or Checker) references some object, the Tile's clone still references the same object (rather than a copy of it).

On the other hand, your serialization code is a well known practice for creating a deep copy of your board: The whole tree of dependent objects is serialized and deserialized.

Of course, this only makes a difference if your Tiles (or Checkers) contain fields with reference types.

Related Question