Effettuare shallow e deep copy di un reference type

di Ugo Lattanzi, in ASP.NET 2.0,

Molto spesso nelle nostre applicazioni abbiamo l'esigenza di duplicare un reference type ma a volte questa operazione può risultare parecchio scomoda e addirittura dispendiosa nel caso in cui il nostro oggetto abbia un gran numero di proprietà.

Prima di duplicare un oggetto è giusto pensare al tipo di duplicazione di cui si ha bisogno, se una Shallow o una Deep Copy.

Per capire la differenza tra i due tipi di copia si provi ad immaginare un oggetto User che ha al suo interno una collection di roles; se duplichiamo User dobbiamo duplicare anche il valore della proprietà Roles, oppure dobbiamo mantenere il riferimento agli oggetti stessi?
Provando ad immaginare una situazione in un ambiente reale, ci si rende conto che la risposta non è del tutto scontata.

Per effetture la duplicazione esclusivamente dell'oggetto padre (Shallow Copy) il .NET Framework ci viene incontro fornendo il metodo MemberwiseClone della classe System.Object, che è di tipo protected e quindi utilizzabile dalla classe stessa e da tutte le derivate.
Poichè tutte le nostre classi derivano da Object, non avremo nessun problema ad invocare il metodo.

Al contrario, la Deep Copy è più complessa da realizzare in quanto è necessario creare una nuova istanza per ogni reference type presente nell'oggetto e assegnargli i valori.
Una soluzione è serializzare l'oggetto in memoria per poi deserializzarlo.
Ovviamente l'operazione è più onerosa rispetto alla shallow copy e richiede che l'oggetto abbia l'attributo Serializable.

Il codice seguente mostra un metodo generico da utilizzare per effettuare una Deep Copy di qualsiasi oggetto serializzabile.

public static T DeepCopy<T>(T myObj)
{
  using (MemoryStream stream = new MemoryStream())
  {
    try
    {
      BinaryFormatter bFormatter = new BinaryFormatter();
      bFormatter.Serialize(stream, myObj);
      stream.Seek(0, SeekOrigin.Begin);
      return (T)bFormatter.Deserialize(stream);
    }
    catch (Exception)
    {
      throw;
    }
  }
}

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi