Programmēšana

Mani divi centi par Deep copy vs Sekla kopija .Net

Microsoft .Net nodrošina objektu klonēšanas atbalstu - iespēju izveidot precīzu objekta kopiju (sauktu arī par klonu). Klonēšana var būt divu veidu: sekla un dziļa kopija. Lai gan pirmo var ieviest, izsaucot sistēmas MemberwiseClone metodi. Object, pēdējās ieviešana ir nedaudz grūts, jo pēc noklusējuma jums tas nav pieejams sistēmā. Būtībā, kamēr sekla kopija atsaucēs kopē atsauces objektus, dziļais klons kopā ar atsaucēm izveido avota objekta kopiju.

Kādas ir visas pieejamās iespējas klonēšanai?

Lai klonētu klases instanci C #, jums ir dažas iespējas, no kurām izvēlēties. Tie ietver sekojošo:

  • Izmantojot metodi System.Object.MemberwiseClone, lai veiktu seklu kopiju
  • Reflection izmantošana, izmantojot Activator.CreateInstance metodi
  • Serializācijas izmantošana
  • Ieviešot IClonable saskarni

Ņemiet vērā, ka, klonējot objektus vai klašu gadījumus .net, jums nav jāņem vērā statiskie dalībnieki vai statiskie lauki. Iemesls ir tāds, ka statiskie objekti tiek glabāti koplietotās atmiņas vietā, un jums katram lietojumprogrammas domēnam ir piešķirta viena atmiņas vieta.

Sekla kopija pret dziļu kopiju

Apsveriet klases darbinieku un ka mēs izveidojam darbinieku klases eksemplāru, kā parādīts zemāk.

Darbinieku emp = jauns darbinieks ();

Darbinieku klons = emp;

Skatiet iepriekš minēto koda fragmentu. Piešķiršanas operators "=" kopētu atsauci, nevis faktisko objektu. MemberwiseClone () metode, kas definēta sistēmā System.Object, dara tieši to pašu. Šie ir sekla kopiju piemēri. Tādējādi, kad izmantojat piešķiršanas operatoru, lai kopētu un iebilstu citā, vai, izmantojot metodi Memberwise.Clone (), jūs faktiski darāt sekla objekta kopiju.

Kamēr seklā eksemplārā kopētā objekta dalībnieki atsaucas uz to pašu objektu kā sākotnējais objekts, dziļā kopijā katram no sākotnējā eksemplāra atsauces tipa dalībniekiem tiek izveidoti atsevišķi gadījumi jaunajā vai klonētajā instancē. Tādējādi, ja sākotnējā instancē ir atsauces tips, jaunajā instancē būs arī viens un tas pats atsauces tipa loceklis, bet šis atsauces tips norādīs uz pilnīgi jaunu gadījumu.

Seklā eksemplārā tiek izveidots jauns objekts, un pēc tam avota objekta nemestiskie dalībnieki tiek kopēti mērķa objektā vai jaunajā objektā. Ja dalībnieks ir vērtības tipa lauks, tiek veikta lauka kopija pa bitam. Turpretī, ja kopējamais dalībnieks ir atsauces tips, atsauce tiek kopēta. Tādējādi atsauces loceklis oriģinālajā objektā un mērķa objektos attiecas uz to pašu objektu atmiņā.

Ja jums ir kolekcija ar atsevišķiem elementiem iekšā un jūs vēlaties veikt sekla kopiju kolekcijas instancē. Jāatzīmē, ka sekla kolekcijas eksemplāra kopija kolekcijas struktūru, bet ne kolekcijas iekšējos elementus. Tādējādi, pēc tam, kad esat veicis seklu kolekcijas kopijas kopiju, jums būs divas kolekcijas, kas koplietos atsevišķus kolekcijas elementus. Gluži pretēji, ja veicat dziļu kolekcijas eksemplāra kopiju, jums būs divi kolekcijas gadījumi ar atsevišķu oriģinālās kolekcijas elementu dublēšanu.

Dziļās kopijas ieviešana, izmantojot serializāciju

Dziļo kopiju var ieviest dažādos veidos. Viens no vēlamākajiem veidiem, kā ieviest dziļu objekta kopiju, ir serializācijas izmantošana. Varat arī izmantot refleksiju, lai veiktu klases eksemplāra dziļu kopiju. Šis koda fragments parāda, kā jūs varat uzrakstīt metodi, kas īsteno bināro sērijveidošanu, lai veiktu dziļu eksemplāra kopiju, izmantojot C #.

publiskā statiskā T DeepCopy (T obj)

       {

ja (! typeof (T) .IrSerializējams)

           {

mest jaunu izņēmumu ("Avota objektam jābūt seriālizējamam");

           }

ja (Object.ReferenceEquals (obj, null))

           {

mest jaunu izņēmumu ("Avota objekts nedrīkst būt nulle");

           }

T rezultāts = noklusējums (T);

izmantojot (var memoryStream = new MemoryStream ())

           {

var formatter = new BinaryFormatter ();

formatēt.Serializēt (memoryStream, obj);

memoryStream.Sek (0, SeekOrigin.Begin);

rezultāts = (T) formatētājs. Dezerializēt (memoryStream);

memoryStream.Close ();

           }

atgriešanās rezultāts;

       }

Ņemot vērā to, ka jums ir entītijas klase ar nosaukumu Darbinieks, varat veikt dziļu Darbinieku klases instances dziļu kopiju, kā parādīts zemāk esošajā koda fragmentā.

static void Main (virkne [] args)

       {

Darbinieku emp = jauns darbinieks ();

emp.EmployeeId = 1;

emp.Vārds = "Joydip";

emp.LastName = "Kanjilal";

Darbinieku klons = DeepCopy (emp);

ja (Object.ReferenceEquals (emp, klons))

           {

Console.WriteLine ("Atsauces ir vienādas.");

           }

cits

           {

Console.WriteLine ("Atsauces ir atšķirīgas.");

           }

       }

Izpildot iepriekš minēto programmu, tiks veikta dziļa eksemplāra "emp" kopija un ziņojums "Atsauces ir atšķirīgas". tiks parādīts.

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