En C #, quelle est la méthode préférée pour ajouter une fonctionnalité de copie (profonde) à une classe? Faut-il implémenter le constructeur de copie, ou plutôt dériver de ICloneable et implémenter la méthode Clone ()?
Le problème avec ICloneableest, comme d'autres l'ont mentionné, qu'il ne spécifie pas s'il s'agit d'une copie profonde ou superficielle, ce qui la rend pratiquement inutilisable et, en pratique, rarement utilisée. Il revient également object, ce qui est pénible, car il nécessite beaucoup de casting. (Et bien que vous ayez spécifiquement mentionné les classes dans la question, la mise ICloneableen œuvre sur un structnécessite de la boxe.)
Un constructeur de copie souffre également de l'un des problèmes liés à ICloneable. Il n'est pas évident qu'un constructeur de copie effectue une copie profonde ou superficielle.
Account clonedAccount = new Account(currentAccount); // Deep or shallow?
Il serait préférable de créer une méthode DeepClone (). De cette façon, l'intention est parfaitement claire.
Cela soulève la question de savoir s'il doit s'agir d'une méthode statique ou d'instance.
Account clonedAccount = currentAccount.DeepClone(); // instance method
ou
Account clonedAccount = Account.DeepClone(currentAccount); // static method
Je préfère parfois légèrement la version statique, simplement parce que le clonage semble être quelque chose qui est fait à un objet plutôt que quelque chose que l'objet fait. Dans les deux cas, il y aura des problèmes à résoudre lors du clonage d'objets qui font partie d'une hiérarchie d'héritage, et la façon dont ces problèmes sont résolus peut finalement conduire la conception.
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();
}
}