Programmering

Mine to øre på Deep copy vs Shallow copy i .Net

Microsoft .Net gir støtte for kloning av objekter - en mulighet til å lage en nøyaktig kopi av et objekt (også kjent som en klon). Kloning kan være av to typer: grunne kopier og dype kopier. Mens førstnevnte kan implementeres ved å ringe til MemberwiseClone-metoden til System.Object-klassen, er implementering av sistnevnte litt vanskelig, da du ikke har støtte for det i rammeverket som standard. I det vesentlige, mens en grunne kopi kopierer referansene sans de refererte objektene, oppretter en dyp klon en kopi av kildeobjektet sammen med referansene.

Hva er alle tilgjengelige alternativer for kloning?

For å klone en forekomst av en klasse i C #, har du noen alternativer å velge mellom. Disse inkluderer følgende:

  • Ved hjelp av System.Object.MemberwiseClone-metoden for å utføre en grunne kopi
  • Bruke refleksjon ved å dra nytte av Activator.CreateInstance-metoden
  • Bruker serialisering
  • Ved å implementere det IClonable grensesnittet

Vær oppmerksom på at når du kloner objekter eller forekomster av klasser i .Net, trenger du ikke ta hensyn til statiske medlemmer eller statiske felt. Årsaken er at statiske objekter er lagret på et delt minneplassering, og at du har en minneplassering tildelt per applikasjonsdomene.

Grunn kopi kontra dyp kopi

Tenk på en klassemedarbeider og at vi oppretter en forekomst av medarbeiderklassen som vist nedenfor.

Employee emp = ny ansatt ();

Ansatt klone = emp;

Se kodebiten ovenfor. Oppdragsoperatøren "=" kopierer referansen og ikke det faktiske objektet. MemberwiseClone () -metoden definert i System.Object-klassen gjør nøyaktig det samme. Dette er eksempler på grunne kopier. Derfor når du bruker en oppdragsoperatør til å kopiere og motsette deg en annen, eller bruke metoden Memberwise.Clone (), gjør du faktisk en grunne kopi av objektet.

Mens i grunne kopier refererer medlemmene av det kopierte objektet til det samme objektet som det opprinnelige objektet, i en dyp kopi opprettes separate forekomster av hvert av referansetypemedlemmene i den opprinnelige forekomsten i den nye eller klonede forekomsten. Derfor, hvis du har en referansetype i den opprinnelige forekomsten, vil den nye forekomsten også inneholde samme referansetypemedlem i den, men denne referansetypen vil peke på en helt ny forekomst.

I grunne kopier opprettes et nytt objekt, og deretter kopieres ikke-statiske medlemmer av kildeobjektet til målobjektet eller det nye objektet. Hvis medlemmet er et felt av verditype, utføres en bit for bit-kopi av feltet. I kontrast, hvis medlemmet som kopieres er en referansetype, blir referansen kopiert. Derfor refererer elementet inne i det opprinnelige objektet og målobjektene til det samme objektet i minnet.

Hvis du har en samling med individuelle elementer inni, og du vil utføre en grunne kopi av samlingsforekomsten. Det skal bemerkes at en grunne kopi av en samlingsforekomst kopierer samlingenes struktur, men ikke elementene i samlingen. Derfor, etter at du har utført en grunne kopi av samlingsforekomsten, vil du ha to samlinger som deler de enkelte elementene i samlingen. Tvert imot, hvis du utfører en dyp kopi av samlingsforekomsten, vil du ha to samlingsforekomster med de enkelte elementene i den originale samlingen duplisert.

Implementering av dyp kopi ved hjelp av serialisering

Du kan implementere dypkopi på mange måter. En av de mest foretrukne måtene å implementere en dyp kopi av et objekt er ved å bruke serialisering. Du kan også bruke refleksjon for å utføre en dyp kopi av en forekomst av en klasse. Følgende kodebit illustrerer hvordan du kan skrive en metode som implementerer binær serialisering for å utføre en dyp kopi av en forekomst ved hjelp av C #.

offentlig statisk T DeepCopy (T obj)

       {

if (! typeof (T) .IsSerializable)

           {

kaste nytt unntak ("Kildeobjektet må serialiseres");

           }

if (Object.ReferenceEquals (obj, null))

           {

kaste nytt unntak ("Kildeobjektet må ikke være null");

           }

T resultat = standard (T);

bruker (var memoryStream = ny MemoryStream ())

           {

var formatter = new BinaryFormatter ();

formatter.Serialize (memoryStream, obj);

memoryStream.Seek (0, SeekOrigin.Begin);

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

memoryStream.Close ();

           }

returresultat;

       }

Tatt i betraktning at du har en enhetsklasse kalt Employee, kan du utføre en dyp kopi av en forekomst av Employee-klassen som vist i kodebiten nedenfor.

statisk tomrom Main (streng [] args)

       {

Employee emp = ny ansatt ();

emp.EmployeeId = 1;

emp.FirstName = "Joydip";

emp.LastName = "Kanjilal";

Ansatt klone = DeepCopy (emp);

if (Object.ReferenceEquals (emp, klone))

           {

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

           }

ellers

           {

Console.WriteLine ("Referanser er forskjellige.");

           }

       }

Når du kjører programmet ovenfor, vil en dyp kopi av forekomsten "emp" bli utført og meldingen "Referanser er forskjellige." vises.

$config[zx-auto] not found$config[zx-overlay] not found