FreeTime - Stefano Passatordi 's Blog


Libera la mente...ecco il Blog di Stefano Passatordi
Statistiche
  • Views Home Page: 135.436
  • Views Posts: 316.556
  • Views Gallerie: 491.663
  • n° Posts: 210
  • n° Commenti: 148
Archivio Posts
Anno 2010

Anno 2009

Anno 2008

Anno 2007

Anno 2006

Anno 2005
Mappa

Shallow copy VS Deep copy

I am back! Dopo quasi due mesi di totale assenza (studio troppo..questo è il mio problema! )!

Parliamo di come effettuare la copia di un oggetto con C#, prima però un pò di teoria!
Le tecniche per effettuare la copia di un oggetto sono essenzialmente due : Shallow copy e Deep copy.
La Shallow copy effettua una copia parziale di un oggetto mentre la Deep copy esegue una copia completa. Copia parziale vuol dire che con la shallow copy vengono copiati solo i campi con valore (ad esempio campi di tipo int) e non i campi con riferimenti (ad esempio campi di tipo oggetto in generale). Questo vuol dire che l'oggetto originale e la sua copia condivideranno i campi riferimento. Quindi, una modifica effettuata al riferimento, sarà visibile sia dall'oggetto originale che dalla sua copia...spesso questa cosa è inutile e/o scomoda!
Per effettuare una copia completamente indipendente dall'originale allora si fa ricorso alla deep copy.

Vediamo in C# come implementare sia la shallow copy che la deep copy!

Prendiamo, ad esempio, una classe Nodo che rappresenta appunto un nodo di un albero qualsiasi.

   
    public class Nodo
    {

        public Nodo(string content)
        {
            this.Text = content;
            this.Children = new List<Nodo>();
            this.Parents = new List<Nodo>();
        }

        private string text;
        public string Text
        {
            get { return text; }
            set { text = value; }
        }

        private List<Nodo> parents;
        internal List<Nodo> Parents
        {
            get { return parents; }
            set { parents = value; }
        }

        private List<Nodo> children;
        internal List<Nodo> Children
        {
            get { return children; }
            set { children = value; }
        }

        public void AddChild(Nodo node)
        {
            this.Children.Add(node);
        }

        public void AddParent(Nodo node)
        {
            this.Parents.Add(node);
        }

        public void RemoveChild(int index)
        {
            if(this.Children.Count > index)
                this.Children.RemoveAt(index);
        }

        public void RemoveParent(int index)
        {
            if(this.Parents.Count > index)
                this.Parents.RemoveAt(index);
        }    
           
    }

Questa classe ha una propretà di tipo string e due di tipo collection, questo vuol dire che la shallow copy non avrebbe senso perchè tutti i campi sarebbero in comune con la copia. Modificando la proprietà text della copia si modificherebbe anche l'originale.
Per chi fosse interessato, per la shallow copy :

Nodo root = new Nodo("originale");
Nodo root_copy = root; // shallow copy

root_copy.Text = "copia"; // questo imposta anche la proprietà text di root al valore "copia"!!!

Per effettuare la deep copy sfruttiamo la serializzazione...
Prima di tutto importiamo :

using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

Poi aggiungiamo alla classe Nodo l'attributo : [Serializable] e facciamo ereditare da ICloneable.
Quindi dovremo avere :

[Serializable]
    public class Nodo : ICloneable
    {

        public Nodo(string content)
        {
            this.Text = content;
            this.Children = new List<Nodo>();
            this.Parents = new List<Nodo>();
        }
       ......
     }

Aggiungiamo poi il metodo Clone() :

[Serializable]
    public class Nodo : ICloneable
    {

        public Nodo(string content)
        {
            this.Text = content;
            this.Children = new List<Nodo>();
            this.Parents = new List<Nodo>();
        }
       ......

        public object Clone()
        {
            MemoryStream ms = new MemoryStream();

            BinaryFormatter bf = new BinaryFormatter();

            bf.Serialize(ms, this);

            ms.Position = 0;

            object obj = bf.Deserialize(ms);

            ms.Close();

            return obj;
        }

     }

Adesso possiamo effettuare la deep copy :

Nodo root = new Nodo("originale");
Nodo root_copy = (Nodo)root.Clone(); //deep copy

root_copy.Text = "copia"; // questo NON imposta anche la proprietà text di root al valore "copia" ma lascia "originale"!!! I due oggetti sono indipendenti.

L'interfaccia IClonable stabilisce che l'oggetto può essere duplicato. Ha un solo metodo :

public interface IClonable {
    Object Clone();
}

Alla classe che eredita il compito di implementare questo metodo. Per la shallow copy è possibile sfruttare questa interfaccia in questo modo :

public object Clone()
{
   return Memberwiseclone();
}

Mentre per la deep copy una implementazione possibile è quella vista in precedenza che si basa sulla serializzazione.

Questo è tutto per adesso

Enjoy!
Categoria: Programmazione
mercoledì, 12 set 2007 Ore. 19.36
Ora e Data
Calendario
ottobre 2017
lmmgvsd
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345
Blogs Amici
    Links
      Copyright © 2002-2007 - Blogs 2.0
      dotNetHell.it | Home Page Blogs
      ASP.NET 2.0 Windows 2003