In C#, what is the preferred way to add (deep) copy functionality to a class?
Should one implement the copy constructor,
or rather derive from ICloneable and implement the Clone() method?
The problem with ICloneable
is, as others have mentioned, that it does not specify whether it is a deep or shallow copy, which makes it practically unuseable and, in practice, rarely used. It also returns object
, which is a pain, since it requires a lot of casting. (And though you specifically mentioned classes in the question, implementing ICloneable
on a struct
requires boxing.)
A copy constuctor also suffers from one of the problems with ICloneable. It isn't obvious whether a copy constructor is doing a deep or shallow copy.
Account clonedAccount = new Account(currentAccount); // Deep or shallow?
It would be best to create a DeepClone() method. This way the intent is perfectly clear.
This raises the question of whether it should be a static or instance method.
Account clonedAccount = currentAccount.DeepClone(); // instance method
or
Account clonedAccount = Account.DeepClone(currentAccount); // static method
I slightly prefer the static version sometimes, just because cloning seems like something that is being done to an object rather than something the object is doing. In either case, there are going to be issues to deal with when cloning objects that are part of an inheritence hierarchy, and how those issues are delt with may ultimately drive the design.
class CheckingAccount : Account
{
CheckAuthorizationScheme checkAuthorizationScheme;
public override Account DeepClone()
{
CheckingAccount clone = new CheckingAccount();
DeepCloneFields(clone);
return clone;
}
protected override void DeepCloneFields(Account clone)
{
base.DeepCloneFields(clone);
((CheckingAccount)clone).checkAuthorizationScheme = this.checkAuthorizationScheme.DeepClone();
}
}