Em C #, qual é a maneira preferida de adicionar funcionalidade de cópia (profunda) a uma classe? Deve-se implementar o construtor de cópia, ou melhor, derivar de ICloneable e implementar o método Clone ()?
O problema com ICloneableé, como outros mencionaram, que não especifica se é uma cópia profunda ou superficial, o que a torna praticamente inutilizável e, na prática, raramente usada. Também retorna object, o que é chato, pois requer muito casting. (E embora você tenha mencionado especificamente as classes na pergunta, a implementação ICloneableem um structrequer boxe.)
Um construtor de cópia também sofre de um dos problemas com o ICloneable. Não é óbvio se um construtor de cópia está fazendo uma cópia profunda ou superficial.
Account clonedAccount = new Account(currentAccount); // Deep or shallow?
Seria melhor criar um método DeepClone (). Dessa forma, a intenção é perfeitamente clara.
Isso levanta a questão de saber se deve ser um método estático ou de instância.
Account clonedAccount = currentAccount.DeepClone(); // instance method
ou
Account clonedAccount = Account.DeepClone(currentAccount); // static method
Às vezes, prefiro um pouco a versão estática, só porque a clonagem parece algo que está sendo feito em um objeto, em vez de algo que o objeto está fazendo. Em ambos os casos, haverá problemas com os quais lidar ao clonar objetos que fazem parte de uma hierarquia de herança, e como esses problemas são resolvidos pode, em última instância, conduzir o 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();
}
}