Memberwiseclone of aggregates

Asked

Viewed 125 times

3

I have in memory (not yet stored in database) an object of type List<NotaFiscal>. I need to pass an item from this list as a parameter to a screen to make changes to that object. However it may be necessary for the user to cancel the changes, and object to return to its original state.

Then, when opening the screen you will receive this object from NotaFiscal, I clone this object using MemberwiseClone().

Class Notafiscal

public class NotaFiscal
{
    public string Numero { get; set; }
    public string Serie { get; set; }
    .........
    public ICollection<NotaFiscalProduto> Produtos { get; set; }

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

Class Telanotafiscal

public partial class TelaNotaFiscal: Window
{
     private readonly NotaFiscal _notaBackup;
     private readonly NotaFiscal _nota;
     private bool _cancelarAlteracao;

     public NotaFiscal Nota => !_cancelarAlteracao ? _nota : _notaBackup;

     public TelaNotaFiscal(NotaFiscal nota)
     {
         InitializeComponent();
         _notaBackup = nota.Clone();
         _nota = nota;
     }
 }

Class Telegraphy

 private void btnNf_Click(object sender, RoutedEventArgs e)
 {
    var botao = (Button)sender;
    var nota = (NotaFiscal)botao.DataContext;
    var telaNota = new TelaNotaFiscal(nota);
    telaNota.Closed += (sen, es) =>
    {
       nota = telaNota.Nota;
     };
     telaNota .ShowDialog();
  }

If the user cancels the change, the properties Numero and Serie return to the previous value. However, if _nota.Produtos, this is also reflected in _notaBackup.Produtos

Immediate Window

Analyzing the Immediacy I can conclude that the objects _nota and _notaBackup are different, but the zero positions of Produtos are the same objects.

_note. Products[0]. Gethashcode()

45644990

_notaBackup.Products[0]. Gethashcode()

45644990

_note.Gethashcode()

59505294

_notaBackup.Gethashcode()

23797978

What could you do to fix this problem? Or what other alternative to edit this object in memory and reverse the changes if necessary.

  • 1

    I think the GetHashCode() does not do what you imagine. Different objects with equal values will have the same hashcode.

  • I didn’t know that. "I found" this sort of unique object identifier. Thank you

  • The unique identifier of the object is the object itself and it is only valid under certain circumstances.

  • http://answall.com/questions/184019/o-que%C3%A9-hashcode-e-qual-sua-finalidade/184034#184034

1 answer

3


You need to make a deep copy. Now I talked about it in another question.

It is not easy to do this the right way. The simplest and safest is to serialize and deserialize the object. Today almost everyone wears Newtonsoft JSON for this. Actually now you have the System.Text.Json which is the highest preference for several reasons, even though it is not as powerful, can not handle all situations, but almost all.

Do something like that:

public NotaFiscal Clone() {
    if (Object.ReferenceEquals(source, null)) {
        return default(NotaFiscal);
    }
    var deserializeSettings = new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace};
    return JsonConvert.DeserializeObject<NotaFiscal>(JsonConvert.SerializeObject(this), deserializeSettings);

 }

I put in the Github for future reference.

Obviously you can do this as a utility or extension method as well. I did it the way it started.

If something is not serializable you may have problems. The solution is probably to use reflection and copy all fields of the entire object graph. Nothing simple task and I won’t even get into it.

  • I hadn’t thought about serialization. I’ll try and see if it meets.

  • Making the copy with serialization worked! Thank you

Browser other questions tagged

You are not signed in. Login or sign up in order to post.