Programovanie

Moje dva centy za hlbokú kópiu a plytkú kópiu v sieti .Net

Microsoft .Net poskytuje podporu pre klonovanie objektov - schopnosť vytvárať presnú kópiu objektu (tiež známy ako klon). Klonovanie môže byť dvoch typov: plytké a hlboké. Zatiaľ čo prvé je možné implementovať pomocou volania metódy MemberwiseClone triedy System.Object, implementácia druhého je trochu zložitá, pretože v predvolenom nastavení preň nemáte podporu. V zásade platí, že zatiaľ čo plytká kópia kopíruje referencie bez odkazovaných objektov, hlboký klon vytvára kópiu zdrojového objektu spolu s jeho referenciami.

Aké sú všetky dostupné možnosti klonovania?

Ak chcete naklonovať inštanciu triedy v C #, máte na výber z niekoľkých možností. Medzi ne patria:

  • Použitie metódy System.Object.MemberwiseClone na vykonanie plytkej kópie
  • Použitie reflexie využitím výhody metódy Activator.CreateInstance
  • Používanie serializácie
  • Implementáciou IClonable rozhrania

Upozorňujeme, že pri klonovaní objektov alebo inštancií tried v .Net nemusíte brať do úvahy statické členy alebo statické polia. Dôvod je ten, že statické objekty sú uložené v zdieľanej pamäti a pre každú doménu aplikácie je pre ne vyhradené jedno pamäťové miesto.

Plytká kópia vs. hlboká kópia

Zvážte triedu Zamestnanec a že vytvoríme inštanciu triedy Zamestnanec, ako je uvedené nižšie.

Zamestnanecké emp = nový zamestnanec ();

Zamestnanecký klon = emp;

Prečítajte si útržok kódu vyššie. Operátor priradenia "=" skopíruje odkaz a nie skutočný objekt. Metóda MemberwiseClone () definovaná v triede System.Object robí presne to isté. Toto sú príklady plytkej kópie. Ak teda použijete operátor priradenia na kopírovanie a vznesenie námietky proti inému, alebo použijete metódu Memberwise.Clone (), v skutočnosti robíte plytkú kópiu objektu.

Zatiaľ čo v plytkej kópii odkazujú členovia kopírovaného objektu na rovnaký objekt ako pôvodný objekt, v hĺbkovej kópii sa v novej alebo klonovanej inštancii vytvoria samostatné inštancie každého z členov referenčného typu v pôvodnej inštancii. Ak teda máte referenčný typ v pôvodnej inštancii, nová inštancia bude v ňom obsahovať aj rovnakého člena referenčného typu, ale tento referenčný typ bude smerovať na úplne novú inštanciu.

V plytkej kópii sa vytvorí nový objekt a potom sa nestatické členy zdrojového objektu skopírujú do cieľového objektu alebo do nového objektu. Ak je členom pole typu hodnoty, vykoná sa kúsok po kúsku poľa. Naproti tomu, ak je kopírovaným členom referenčný typ, referencia sa skopíruje. Preto referenčný člen vo vnútri pôvodného objektu a cieľové objekty odkazujú na rovnaký objekt v pamäti.

Ak máte kolekciu s jednotlivými prvkami vo vnútri a chcete vykonať plytkú kópiu inštancie kolekcie. Je potrebné poznamenať, že plytká kópia inštancie kolekcie kopíruje štruktúru kolekcie, ale nie prvky vo vnútri kolekcie. Preto po vykonaní plytkej kópie inštancie kolekcie budete mať dve kolekcie zdieľajúce jednotlivé prvky kolekcie. Naopak, ak vykonáte hlbokú kópiu inštancie kolekcie, mali by ste dve inštancie kolekcie s duplikovanými jednotlivými prvkami pôvodnej kolekcie.

Implementácia hlbokej kópie pomocou serializácie

Hlbokú kópiu môžete implementovať mnohými spôsobmi. Jedným z najpreferovanejších spôsobov implementácie hĺbkovej kópie objektu je použitie serializácie. Môžete tiež využiť reflexiu na vykonanie hĺbkovej kópie inštancie triedy. Nasledujúci úryvok kódu ilustruje, ako môžete napísať metódu, ktorá implementuje binárnu serializáciu na vykonanie hĺbkovej kópie inštancie pomocou C #.

verejný statický T DeepCopy (T obj)

       {

if (! typeof (T) .IsSerializable)

           {

throw new Exception ("Zdrojový objekt musí byť serializovateľný");

           }

if (Object.ReferenceEquals (obj, null))

           {

throw new Exception ("Zdrojový objekt nesmie mať hodnotu null");

           }

T výsledok = predvolený (T);

pomocou (var memoryStream = nový MemoryStream ())

           {

var formatter = new BinaryFormatter ();

formatter.Serialize (memoryStream, obj);

memoryStream.Seek (0, SeekOrigin.Begin);

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

memoryStream.Close ();

           }

návratový výsledok;

       }

Vzhľadom na to, že máte triedu entít s názvom Zamestnanec, môžete vykonať hĺbkovú kópiu inštancie triedy Zamestnanec, ako je uvedené v útržku kódu nižšie.

static void Main (reťazec [] args)

       {

Zamestnanecké emp = nový zamestnanec ();

emp.EmployeeId = 1;

emp.FirstName = "Joydip";

emp.LastName = "Kanjilal";

Zamestnanecký klon = DeepCopy (emp);

if (Object.ReferenceEquals (emp, clone))

           {

Console.WriteLine („Odkazy sú rovnaké.“);

           }

inak

           {

Console.WriteLine („Odkazy sa líšia.“);

           }

       }

Po vykonaní vyššie uvedeného programu by sa vykonala hlboká kópia inštancie „emp“ a správa „Odkazy sa líšia.“ sa zobrazí.

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