Programování

Moje dva centy na Deep copy vs Shallow copy v .Net

Microsoft .Net poskytuje podporu pro klonování objektů - schopnost vytvořit přesnou kopii objektu (známého také jako klon). Klonování může být dvou typů: mělká kopie a hluboká kopie. Zatímco první lze implementovat voláním metody MemberwiseClone třídy System.Object, implementace druhé je trochu složitá, protože pro ni ve výchozím nastavení nemáte podporu. V podstatě, zatímco mělká kopie kopíruje odkazy bez referenčních objektů, hluboký klon vytváří kopii zdrojového objektu spolu s jeho odkazy.

Jaké jsou všechny dostupné možnosti klonování?

Chcete-li naklonovat instanci třídy v C #, máte na výběr z několika možností. Patří mezi ně následující:

  • Pomocí metody System.Object.MemberwiseClone provést mělkou kopii
  • Použití reflexe využitím výhody metody Activator.CreateInstance
  • Používání serializace
  • Implementací IClonable rozhraní

Všimněte si, že při klonování objektů nebo instancí tříd v .Net nemusíte uvažovat o statických členech nebo statických polích. Důvodem je to, že statické objekty jsou uloženy v umístění sdílené paměti a máte pro ně přidělené jedno umístění paměti na doménu aplikace.

Mělká kopie vs. hluboká kopie

Zvažte třídu Zaměstnanec a že vytvoříme instanci třídy Zaměstnanec, jak je znázorněno níže.

Zaměstnanec emp = nový zaměstnanec ();

Klon zaměstnanců = emp;

Viz výše uvedený fragment kódu. Operátor přiřazení "=" zkopíruje odkaz a nikoli skutečný objekt. Metoda MemberwiseClone () definovaná ve třídě System.Object dělá přesně to samé. Toto jsou příklady mělké kopie. Proto když používáte operátor přiřazení ke kopírování a namítání do jiného, ​​nebo používáte metodu Memberwise.Clone (), ve skutečnosti děláte mělkou kopii objektu.

Zatímco v mělké kopii odkazují členové kopírovaného objektu na stejný objekt jako původní objekt, v hluboké kopii se v nové nebo klonované instanci vytvoří samostatné instance každého z členů referenčního typu v původní instanci. Pokud tedy máte v původní instanci referenční typ, nová instance bude v něm také obsahovat stejného člena referenčního typu, ale tento referenční typ bude odkazovat na zcela novou instanci.

V mělké kopii je vytvořen nový objekt a poté jsou nestatické členy zdrojového objektu zkopírovány do cílového objektu nebo nového objektu. Pokud je členem pole typu hodnoty, provede se bitová kopie pole. Naproti tomu, pokud je kopírovaný člen typ odkazu, je odkaz zkopírován. Referenční člen uvnitř původního objektu a cílové objekty tedy odkazují na stejný objekt v paměti.

Pokud máte kolekci s jednotlivými prvky uvnitř a chtěli byste provést mělkou kopii instance kolekce. Je třeba poznamenat, že mělká kopie instance kolekce kopíruje strukturu kolekce, ale ne prvky uvnitř kolekce. Proto po provedení mělké kopie instance kolekce byste měli dvě kolekce, které sdílejí jednotlivé prvky kolekce. Naopak, pokud provedete hlubokou kopii instance kolekce, měli byste dvě instance kolekce s duplikovanými jednotlivými prvky původní kolekce.

Implementace hlubokých kopií pomocí serializace

Hluboké kopie můžete implementovat mnoha způsoby. Jedním z nejvýhodnějších způsobů implementace hluboké kopie objektu je použití serializace. Můžete také využít reflexi k provedení hluboké kopie instance třídy. Následující fragment kódu ukazuje, jak můžete napsat metodu, která implementuje binární serializaci k provedení hluboké kopie instance pomocí C #.

veřejná statická T DeepCopy (T obj)

       {

if (! typeof (T) .IsSerializable)

           {

vyvolá novou výjimku ("Zdrojový objekt musí být serializovatelný");

           }

if (Object.ReferenceEquals (obj, null))

           {

throw new Exception ("Zdrojový objekt nesmí být null");

           }

T výsledek = výchozí (T);

pomocí (var memoryStream = nový MemoryStream ())

           {

var formatter = new BinaryFormatter ();

formatter.Serialize (memoryStream, obj);

memoryStream.Seek (0, SeekOrigin.Begin);

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

memoryStream.Close ();

           }

vrátit výsledek;

       }

Vzhledem k tomu, že máte třídu entit nazvanou Zaměstnanec, můžete provést hlubokou kopii instance třídy Zaměstnanec, jak je ukázáno v fragmentu kódu níže.

static void Main (řetězec [] args)

       {

Zaměstnanec emp = nový zaměstnanec ();

emp.EmployeeId = 1;

emp.FirstName = "Joydip";

emp.LastName = "Kanjilal";

Klon zaměstnanců = DeepCopy (emp);

if (Object.ReferenceEquals (emp, clone))

           {

Console.WriteLine („Odkazy jsou stejné.“);

           }

jiný

           {

Console.WriteLine („Odkazy se liší.“);

           }

       }

Když spustíte výše uvedený program, provede se hluboká kopie instance „emp“ a zpráva „Odkazy se liší.“ se zobrazí.

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