A interface ICloneable contém o método Clone, responsável por clonar (criar uma cópia) de uma classe.
Porque utilizar
Se ao desenvolver você se depara com um cenário que necessita criar um objeto a partir de outro, mas não quer que ele aponte para o mesmo endereço de memôria do original, você precisará clonar este objeto.
Se você criar um objeto e atribuir o objeto original para este novo, você estará apenas apontando este objeto novo para o mesmo endereço de memôria do antigo, conforme exemplo abaixo. Isto ocorre devido ao .NET ter como princípio que todo objeto é passado como referência.
PessoaEntity pOriginal = new PessoaEntity(); pOriginal.Nome = "Jose Otavio"; /* Ao atribuir o objeto original ao novo, você estará apontando para o mesmo endereço de memória. Se algum dos objetos sofrerem alguma alteração, esta será realizada no mesmo endereço de memôria, ou seja, a alteração será feita para os dois objetos (original e novo). */ PessoaEntity pNovo = pOriginal;Muitas pessoas utilizam uma forma alternativa para clonar um objeto, confome exemplo abaixo.
PessoaEntity pOriginal = new PessoaEntity(); pOriginal.Nome = "Jose Otavio"; PessoaEntity pNovo = new PessoaEntity(); pNovo.Nome = pOriginal.Nome;Esta forma é bastante comum para quem não conhece a interface ICloneable.
Mas imagine que seu objeto tenha várias propriedades, você criará um método com várias linhas para fazer a cópia? Acredito que você achará "feio" fazer desta maneira.
Porque não utilizar o que o .NET te proporciona?
Exemplo
Vamos ao exemplo e criar uma classe que implementa a interface ICloneable.
No método Clone, iremos utilizar o método MemberwiseClone responsável por criar a cópia deste objeto.
public class PessoaEntity : ICloneable
{
public string Nome { get; set; }
public int Idade { get; set; }
public object Clone()
{
return this.MemberwiseClone();
}
}
Utilizando esta classe ficaria:
static void Main(string[] args)
{
PessoaEntity pOriginal = new PessoaEntity();
pOriginal.Nome = "Jose Otavio";
pOriginal.Idade = 27;
PessoaEntity pNovo = (PessoaEntity)pOriginal.Clone();
pNovo.Nome = "jQuaglio";
Console.WriteLine("Nome Original: {0}", pOriginal.Nome);
Console.WriteLine("Idade Original: {0}", pOriginal.Idade.ToString());
Console.WriteLine();
Console.WriteLine("Nome Novo: {0}", pNovo.Nome);
Console.WriteLine("Idade Novo: {0}", pNovo.Idade.ToString());
Console.ReadKey();
}
Saída:
Agora vamos enriquecer a classe Pessoa e mostrar o que muitas pessoas não tem conhecimento.
Imaginamos o cenário de que nesta classe exista uma propriedade com o tipo de um outro objeto.
public class PessoaEntity : ICloneable
{
public string Nome { get; set; }
public int Idade { get; set; }
//Objeto EnderecoEntity
public EnderecoEntity Endereco { get; set; }
public object Clone()
{
return this.MemberwiseClone();
}
}
public class EnderecoEntity
{
public string Logradouro { get; set; }
public string CEP { get; set; }
}
Utilização da classe:
static void Main(string[] args)
{
PessoaEntity pOriginal = new PessoaEntity();
pOriginal.Nome = "Jose Otavio";
pOriginal.Idade = 27;
pOriginal.Endereco = new EnderecoEntity();
pOriginal.Endereco.Logradouro = "Rua XYZ, 15";
pOriginal.Endereco.CEP = "00000-000";
PessoaEntity pNovo = (PessoaEntity)pOriginal.Clone();
pNovo.Nome = "jQuaglio";
pNovo.Endereco.Logradouro = "Avenida ABC, 4000";
Console.WriteLine("Nome Original: {0}", pOriginal.Nome);
Console.WriteLine("Idade Original: {0}", pOriginal.Idade.ToString());
Console.WriteLine("Endereco Original: {0} {1}", pOriginal.Endereco.Logradouro, pOriginal.Endereco.CEP);
Console.WriteLine();
Console.WriteLine("Nome Novo: {0}", pNovo.Nome);
Console.WriteLine("Idade Novo: {0}", pNovo.Idade.ToString());
Console.WriteLine("Endereco Novo: {0} {1}", pNovo.Endereco.Logradouro, pNovo.Endereco.CEP);
Console.ReadKey();
}
Ao executar podemos identificar que o valor das propriedades do objeto original (Endereco) foram alteradas, pois como disse anteriormente, todo objeto é passado por referência, então se alterarmos qualquer instância que aponte para o mesmo endereço, todas as instâncias serão alteradas.
Saída:
Para resolver este problemas, não podemos esquecer de implementar a interface ICloneable na classe EnderecoEntity e alterar o método Clone da classe PessoaEntity para poder clonar este outro objeto.
public class PessoaEntity : ICloneable
{
public string Nome { get; set; }
public int Idade { get; set; }
public EnderecoEntity Endereco { get; set; }
public object Clone()
{
PessoaEntity p = (PessoaEntity)this.MemberwiseClone();
p.Endereco = (EnderecoEntity)p.Endereco.Clone();
return p;
}
}
public class EnderecoEntity : ICloneable
{
public string Logradouro { get; set; }
public string CEP { get; set; }
public object Clone()
{
return this.MemberwiseClone();
}
}
Ao executarmos a mesma saída, teremos:
Lembre-se, ao utilizar a interface ICloneable, não esqueça de clonar todos os objetos que pertencem a classe que será clonada.



Véi, post lindo demais.
ResponderExcluirValeu e Parabéns!
Muito bom o post...
ResponderExcluirMe ajudou muito!