Programmering

Mine to cent på Deep copy vs Shallow copy i .Net

Microsoft .Net understøtter kloning af objekter - en mulighed for at oprette en nøjagtig kopi af et objekt (også kendt som en klon). Kloning kan være af to typer: lav kopi og dyb kopi. Mens førstnævnte kan implementeres ved at ringe til MemberwiseClone-metoden i System.Object-klassen, er implementering af sidstnævnte en smule vanskelig, da du som standard ikke har support til det i rammen. I det væsentlige skaber en dyb klon en kopi af kildeobjektet sammen med dets referencer, mens en lav kopi kopierer referencerne uden for de refererede objekter.

Hvad er alle de tilgængelige muligheder for kloning?

For at klone en forekomst af en klasse i C # har du et par muligheder at vælge imellem. Disse inkluderer følgende:

  • Brug af System.Object.MemberwiseClone-metoden til at udføre en lav kopi
  • Brug af refleksion ved at drage fordel af Activator.CreateInstance-metoden
  • Brug af serialisering
  • Ved at implementere den IClonable interface

Bemærk, at når du kloner objekter eller forekomster af klasser i .Net, behøver du ikke overveje statiske medlemmer eller statiske felter. Årsagen er, at statiske objekter er gemt på en delt hukommelsesplacering, og at du har en hukommelsesplacering tildelt dem pr. Applikationsdomæne.

Lav kopi kontra dyb kopi

Overvej en klassemedarbejder, og at vi opretter en forekomst af medarbejderklassen som vist nedenfor.

Medarbejder emp = ny medarbejder ();

Medarbejderklon = emp;

Se kodestykket ovenfor. Tildelingsoperatøren "=" kopierer referencen og ikke det egentlige objekt. MemberwiseClone () -metoden defineret i System.Object-klassen gør nøjagtigt det samme. Dette er eksempler på lav kopi. Derfor, når du bruger en opgaveoperatør til at kopiere og gøre indsigelse mod en anden, eller ved at bruge metoden Memberwise.Clone (), laver du faktisk en lav kopi af objektet.

Mens medlemmerne af det kopierede objekt i lav kopi henviser til det samme objekt som det originale objekt, oprettes der i en dyb kopi separate forekomster af hvert af referencetypemedlemmerne i den oprindelige forekomst i den nye eller klonede forekomst. Derfor, hvis du har en referencetype i den oprindelige forekomst, vil den nye forekomst også indeholde det samme referencetypemedlem i den, men denne referencetype vil pege på en helt ny forekomst.

I lav kopi oprettes et nyt objekt, og derefter kopieres de ikke-statiske medlemmer af kildeobjektet til målobjektet eller det nye objekt. Hvis medlemmet er et værditypefelt, udføres en bit for bit-kopi af feltet. I modsætning hertil, hvis det medlem, der kopieres, er en referencetype, kopieres referencen. Derfor henviser referenceelementet inde i det originale objekt og målobjekterne til det samme objekt i hukommelsen.

Hvis du har en samling med individuelle elementer indeni, og du gerne vil udføre en lav kopi af samlingsforekomsten. Det skal bemærkes, at en lav kopi af en samlingsinstans kopierer samlingens struktur, men ikke elementerne i samlingen. Derfor, efter at du har udført en lav kopi af samlingsforekomsten, vil du have to samlinger, der deler de enkelte elementer i samlingen. Tværtimod, hvis du udfører en dyb kopi af samlingsinstansen, ville du have to samlingsforekomster med de enkelte elementer i den originale samling duplikeret.

Implementering af dyb kopi ved hjælp af serialisering

Du kan implementere dyb kopi på mange måder. En af de mest foretrukne måder at implementere en dyb kopi af et objekt er ved hjælp af serialisering. Du kan også udnytte refleksion til at udføre en dyb kopi af en forekomst af en klasse. Følgende kodestykke illustrerer, hvordan du kan skrive en metode, der implementerer binær serialisering for at udføre en dyb kopi af en forekomst ved hjælp af C #.

offentlig statisk T DeepCopy (T obj)

       {

hvis (! typeof (T) .IsSerializable)

           {

smid ny undtagelse ("Kildeobjektet skal serienummeres");

           }

hvis (Object.ReferenceEquals (obj, null))

           {

kast ny undtagelse ("Kildeobjektet må ikke være nul");

           }

T resultat = standard (T);

ved hjælp af (var memoryStream = ny MemoryStream ())

           {

var formatter = ny BinaryFormatter ();

formatter.Serialize (memoryStream, obj);

memoryStream.Seek (0, SeekOrigin.Begin);

resultat = (T) formatter.Deserialize (memoryStream);

memoryStream.Close ();

           }

returresultat

       }

I betragtning af at du har en enhedsklasse kaldet Medarbejder, kan du udføre en dyb kopi af en forekomst af medarbejderklassen som vist i kodestykket nedenfor.

statisk ugyldigt Main (streng [] args)

       {

Medarbejder emp = ny medarbejder ();

emp.EmployeeId = 1;

emp.FirstName = "Joydip";

emp.LastName = "Kanjilal";

Medarbejderklon = DeepCopy (emp);

hvis (Object.ReferenceEquals (emp, klon))

           {

Console.WriteLine ("Referencer er de samme.");

           }

andet

           {

Console.WriteLine ("Referencer er forskellige.");

           }

       }

Når du udfører ovenstående program, udføres en dyb kopi af instansen "emp", og meddelelsen "Referencer er forskellige." vises.