Microsoft .Net tukee objektien kloonausta - kykyä luoda tarkka kopio objektista (tunnetaan myös nimellä klooni). Kloonaus voi olla kahta tyyppiä: matala kopio ja syvä kopio. Vaikka ensimmäinen voidaan toteuttaa soittamalla System.Object-luokan MemberwiseClone-menetelmään, jälkimmäisen toteuttaminen on hieman hankalaa, koska sinulla ei ole oletuksena tukea puitteissa. Pohjimmiltaan, kun matala kopio viitteistä ei sisällä viitattuja objekteja, syvä klooni luo kopion lähdeobjektista viitteidensä kanssa.
Mitkä ovat kaikki käytettävissä olevat vaihtoehdot kloonaukselle?
Jos haluat kloonata luokan esiintymän C #: ssä, sinulla on muutama vaihtoehto. Näitä ovat seuraavat:
- System.Object.MemberwiseClone-menetelmän avulla suoritetaan matala kopio
- Reflectionin käyttö hyödyntämällä Activator.CreateInstance-menetelmää
- Sarjallisuuden käyttäminen
- Toteuttamalla IClonable-käyttöliittymä
Huomaa, että kun kloonaat objekteja tai luokkojen esiintymiä .Netissä, sinun ei tarvitse ottaa huomioon staattisia jäseniä tai staattisia kenttiä. Syynä on se, että staattiset objektit tallennetaan jaettuun muistipaikkaan, ja sinulle on varattu yksi muistipaikka sovellusalustaa kohden.
Matala kopio vs. syvä kopio
Harkitse luokan työntekijää ja että luomme esimerkin työntekijän luokasta alla olevan kuvan mukaisesti.
Työntekijän emp = uusi työntekijä ();
Työntekijäklooni = emp;
Katso yllä oleva koodinpätkä. Määritysoperaattori "=" kopioi viitteen eikä varsinaista objektia. System.Object-luokassa määritelty MemberwiseClone () -menetelmä tekee täsmälleen saman. Nämä ovat esimerkkejä matalasta kopiosta. Kun siis kopioit ja vastustat määritysoperaattoria toiselle tai käytät Memberwise.Clone () -menetelmää, teet itse asiassa matalan kopion objektista.
Vaikka matalassa kopiossa kopioidun objektin jäsenet viittaavat samaan objektiin kuin alkuperäinen objekti, syväkopioinnissa uudessa tai kloonatussa ilmentymässä luodaan erilliset esiintymät kustakin alkuperäisen instanssin viitetyyppijäsenestä. Siksi, jos sinulla on viitetyyppi alkuperäisessä ilmentymässä, uusi ilmentymä sisältää myös saman viitetyypin jäsenen, mutta tämä viitetyyppi osoittaa kokonaan uuden ilmentymän.
Pienessä kopiossa luodaan uusi objekti ja sitten lähdeobjektin ei-staattiset jäsenet kopioidaan kohdeobjektiin tai uuteen objektiin. Jos jäsen on arvotyyppikenttä, suoritetaan pikku bitti kopio kentästä. Sitä vastoin, jos kopioitava jäsen on viitetyyppi, viite kopioidaan. Näin ollen alkuperäisen objektin sisällä oleva viitejäsen ja kohdeobjektit viittaavat samaan objektiin muistissa.
Jos sinulla on kokoelma, jossa on yksittäisiä elementtejä, ja haluat tehdä matalan kopion kokoelmaesimerkistä. On huomattava, että matala kopio kokoelmasta kopioi kokoelman rakenteen, mutta ei kokoelman sisällä olevia elementtejä. Kun teet matalan kopion kokoelmaesimerkistä, sinulla on siis kaksi kokoelmaa, jotka jakavat kokoelman yksittäiset elementit. Päinvastoin, jos suoritat koko kopion kokoelman esiintymästä, sinulla on kaksi kokoelmaesimerkkiä, joiden alkuperäisen kokoelman yksittäiset osat kopioidaan.
Syväkopion toteuttaminen sarjallisuuden avulla
Voit toteuttaa syväkopioinnin monin tavoin. Yksi suositeltavimmista tavoista toteuttaa objektin syväkopio on sarjallisuus. Voit myös hyödyntää heijastusta suorittaaksesi syvällisen kopion luokan instanssista. Seuraava koodinpätkä kuvaa, kuinka voit kirjoittaa menetelmän, joka toteuttaa binäärisen sarjoituksen, suorittamaan ilmentymän syvä kopio käyttäen C #: ta.
julkinen staattinen T DeepCopy (T obj)
{
jos (! typeof (T) .Serialisoitavissa)
{
heittää uusi poikkeus ("Lähdeobjektin on oltava sarjoitettavissa");
}
jos (Object.ReferenceEquals (obj, null))
{
heittää uusi poikkeus ("Lähdeobjekti ei saa olla tyhjä");
}
T-tulos = oletus (T);
käyttäen (var memoryStream = uusi MemoryStream ())
{
var formatter = uusi BinaryFormatter ();
muotoilla.Serialize (memoryStream, obj);
memoryStream.Seek (0, SeekOrigin.Begin);
result = (T) formatter.Deserialize (memoryStream);
memoryStream.Close ();
}
paluutulos;
}
Ottaen huomioon, että sinulla on entiteettiluokka nimeltä Työntekijä, voit suorittaa syvän kopion Työntekijä-luokan ilmentymästä alla olevan koodinpätkän mukaisesti.
staattinen void Main (merkkijono [] args)
{
Työntekijän emp = uusi työntekijä ();
emp.EmployeeId = 1;
emp.FirstName = "Joydip";
emp.LastName = "Kanjilal";
Työntekijäklooni = DeepCopy (emp);
jos (Object.ReferenceEquals (emp, klooni))
{
Console.WriteLine ("Viitteet ovat samat.");
}
muu
{
Console.WriteLine ("Viitteet ovat erilaisia.");
}
}
Kun suoritat yllä olevan ohjelman, suoritetaan syvä kopio instanssista "emp" ja viesti "Viitteet ovat erilaiset". tulee näkyviin.