Dərin Clone obyektləri

Kimi bir şey etmək istəyirəm:

 MyObject myObj = GetMyObj(); // Create and fill a new object MyObject newObj = myObj.Clone(); 

Və sonra orijinal obyektə əks olunmayan yeni obyektə dəyişikliklər edin.

Mən tez-tez bu funksiyaya ehtiyac duymıram, buna görə zəruri olduqda yeni bir obyekt yaratmağa başladım və sonra hər bir əmlakı ayrı-ayrılıqda kopyaladım, ancaq həmişə məni vəziyyətdən daha yaxşı və ya daha zərif bir şəkildə həll etmək hissi ilə tərk edir.

Klonlanmış bir obyektin orijinal obyektdə əks olunan dəyişiklik olmadan dəyişdirilə bilməsi üçün necə bir klonu köçürə və ya dərin surətdə kopyalayabilirim?

1844
17 сент. Jordan Arron tərəfindən 17 sentyabrda təyin olundu . 2008-09-17 03:06 '08 at 3:06 2008-09-17 03:06
@ 39 cavab
  • 1
  • 2

Standart praktika ICloneable interfeysini tətbiq etməkdir ( burada təsvir olunacaq, mən də onu tənzimləməyəcəyəm), bir müddət əvvəl Draft Məcəlləsində tapdığım dərin klon klonları üçün yaxşı bir ICloneable və onu məhsullarıma daxil etdi.

Digər bölmələrdə göstərildiyi kimi, bu sizin obyektlərin serializable olması tələb olunur.

 using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; /// <summary> /// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx /// Provides a method for performing a deep copy of an object. /// Binary Serialization is used to perform the copy. /// </summary> public static class ObjectCopier { /// <summary> /// Perform a deep Copy of the object. /// </summary> /// <typeparam name="T">The type of object being copied.</typeparam> /// <param name="source">The object instance to copy.</param> /// <returns>The copied object.</returns> public static T Clone<T>(T source) { if (!typeof(T).IsSerializable) { throw new ArgumentException("The type must be serializable.", "source"); } // Don't serialize a null object, simply return the default for that object if (Object.ReferenceEquals(source, null)) { return default(T); } IFormatter formatter = new BinaryFormatter(); Stream stream = new MemoryStream(); using (stream) { formatter.Serialize(stream, source); stream.Seek(0, SeekOrigin.Begin); return (T)formatter.Deserialize(stream); } } } 

Fikir, sizin obyektinizin seriyalaşdırılması və sonra yeni bir obyektə deserializasiya etməkdir. Üstünlük, bir obyektin çox mürəkkəbləşdiyi zaman hər şeyi klonlaşdırmaqdan narahat olmayın.

Və uzatma metodlarından istifadə edərək (həmçinin orijinal mənbədən):

C # 3.0 uzadılması metodunun yeni metodundan istifadə etməyi xahiş edirsinizsə , metodu aşağıdakı imzaya dəyişin:

 public static T Clone<T>(this T source) { //... } 

İndi üsul sadəcə objectBeingCloned.Clone(); olur objectBeingCloned.Clone(); .

EDIT (10 yanvar 2015) Mən düşündüm ki, bu yaxınlarda (Newtonsoft) Json-ı istifadə etməyə başladım, daha asan olmalıdır və [Serializable] etiketlərin üstünü çəkməyin. ( NB @ conconway, xüsusi üzvlərin JSON metodu ilə klonlanmadığına dair şərhlərdə göstərilmişdir)

 /// <summary> /// Perform a deep Copy of the object, using Json as a serialisation method. NOTE: Private members are not cloned using this method. /// </summary> /// <typeparam name="T">The type of object being copied.</typeparam> /// <param name="source">The object instance to copy.</param> /// <returns>The copied object.</returns> public static T CloneJson<T>(this T source) { // Don't serialize a null object, simply return the default for that object if (Object.ReferenceEquals(source, null)) { return default(T); } // initialize inner objects individually // for example in default constructor some list property initialized with some values, // but in 'source' these items are cleaned - // without ObjectCreationHandling.Replace default constructor values will be added to result var deserializeSettings = new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace}; return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings); } 
1479
17 сент. johnc tərəfindən verilmiş cavab 17 sentyabr . 2008-09-17 03:18 '08 at 3:18 'da 2008-09-17 03:18

Çox sadə obyektlər, əsasən primitivlər və siyahılar üçün bir klon lazımdır. Nesniniz serileştirilmiş JSON ile uyuşmazsa, bu yöntem bu hile yapar. Bu, klonlanmış bir sinifdə modifikasiya və ya interfeyslərin tətbiq edilməsini tələb etmir, JSON.NET kimi bir JSON serializer.

border=0
 public static T Clone<T>(T source) { var serialized = JsonConvert.SerializeObject(source); return JsonConvert.DeserializeObject<T>(serialized); } 
185
03 апр. cavab verildi 03 Apr. 2013-04-03 16:31 '13 at 16:31 2013-04-03 16:31

İkloneable istifadə etməməyin səbəbi ortaq bir interfeysi olmadığından deyil. Bunun səbəbi qeyri-müəyyən olduğu üçün istifadə etmək deyil . Səliqəli və ya dərin surətdə əldə etdiyinizi aydınlaşdırmır; rəssam nədir.

Bəli, MemberwiseClone sadə bir MemberwiseClone edir, lakin MemberwiseClone əksinə Clone deyil; bu, bəlkə də mövcud olmayan DeepClone olardı. ICloneable interfeysi vasitəsilə bir obyekt istifadə etdikdə, əsas obyektin hansı növdə klonlaşdırıldığını bilmirsiniz. (Və XML şərhləri, obyektin klonlama üsulu ilə əlaqəli deyil, interfeysdən şərh aldığı üçün müəyyən edilmir.)

Mən adətən istədiyim hər şeyi edir, yalnız Copy üsulunu edirəm.

149
17 сент. Cavab Ryan Lundy 17 sep tərəfindən verilir . 2008-09-17 04:12 '08 at 4:12 'də 2008-09-17 04:12' də

Buradakı çoxsaylı variantları və bu problemin mümkün həllərini oxuduqdan sonra, bütün variantların Ian P linkində (bütün digər variantlar variantları) çox yaxşı bir şəkildə yekunlaşdırıldığına inanıram və ən yaxşı həllin suallara şərhlərdə Pedro77 linki verilir.

Beləliklə, mən burada sadəcə bu iki linkin müvafiq hissələrini kopyalayıram. Beləliklə, biz:

C kəskin şəkildə obyektlərin klonlanması üçün nə edə biləcəyiniz ən yaxşı şey!

Hər şeydən əvvəl, bunlar bizim seçimlərimizdir:

Ekspres ağaclarını istifadə edərək dərin dərin kopiya , serializasiya, əksiklik və ifadə ağacları ilə klonlama performansını müqayisə edir.

Niyə iCloneable seçirəm (yəni əllə)

Cənab Venkat Subramaniam (artıqlıq bağlantısı burada) niyə ətraflı izah edir .

Çox hallarda tətbiq olunmağa çalışdığı bir nümunə ətrafında bütün ətrafdakı dairələrin məqalələri 3 şəxsiyyətdən istifadə edir: Şəxs, Brain və Şəhər. Biz öz beyninə sahib olan bir insanı klonlaşdırmaq istəyirik, eyni şəhər. Yuxarıda göstərilən metodlardan hər hansı birinin məqaləni gətirib çıxara biləcəyi bütün problemləri yaxından görmək olar.

Bu, mənim çıxışımın yüngül redaktə versiyasıdır:

Bir obyektin bir sinif adı ilə izləyərək New bir obyektin çıxarılması tez-tez kodun uzadılmamasına səbəb olur. Bir klon istifadə edərək, prototip şablonunu istifadə etmək bunun ən yaxşı yolu. Lakin, C # (və Java) üçün nəzərdə tutulmuş bir klon istifadə edərək, olduqca problemli ola bilər. Qorunan (qeyri-ictimai) bir surəti qurucusunu təmin etmək və onu klonlama üsulundan çağırmaq daha yaxşıdır. Bu bizə sinifin bir nümunəsinə bir obyekt yaratmaq vəzifəsini təyin etməyə imkan verir, beləliklə qorunan bir surəti qurucusunu istifadə edərək obyektlərin təhlükəsiz yaradılması kimi genişlənənliyi təmin edir.

Ümid edirik ki, bu tətbiq vəziyyətə aydınlıq gətirə bilər:

 public class Person : ICloneable { private final Brain brain; // brain is final since I do not want // any transplant on it once created! private int age; public Person(Brain aBrain, int theAge) { brain = aBrain; age = theAge; } protected Person(Person another) { Brain refBrain = null; try { refBrain = (Brain) another.brain.clone(); // You can set the brain in the constructor } catch(CloneNotSupportedException e) {} brain = refBrain; age = another.age; } public String toString() { return "This is person with " + brain; // Not meant to sound rude as it reads! } public Object clone() { return new Person(this); } … } 

İndi sinfi şəxsdən nə əldə etdiyini düşünün.

 public class SkilledPerson extends Person { private String theSkills; public SkilledPerson(Brain aBrain, int theAge, String skills) { super(aBrain, theAge); theSkills = skills; } protected SkilledPerson(SkilledPerson another) { super(another); theSkills = another.theSkills; } public Object clone() { return new SkilledPerson(this); } public String toString() { return "SkilledPerson: " + super.toString(); } } 

Aşağıdakı kodu çalıştırmayı cəhd edə bilərsiniz:

 public class User { public static void play(Person p) { Person another = (Person) p.clone(); System.out.println(p); System.out.println(another); } public static void main(String[] args) { Person sam = new Person(new Brain(), 1); play(sam); SkilledPerson bob = new SkilledPerson(new SmarterBrain(), 1, "Writer"); play(bob); } } 

Çıxış olacaq:

 This is person with Brain@1fcc69 This is person with Brain@253498 SkilledPerson: This is person with SmarterBrain@1fef6f SkilledPerson: This is person with SmarterBrain@209f4e 

Qeyd edək ki, obyektlərin sayını saxlayırıqsa, burada tətbiq olunan klon obyektlərin sayının düzgün sayını ehtiva edir.

84
26 сент. Cavab cregox 26 sep verilir . 2012-09-26 23:18 '12 saat 23:18 'da 2012-09-26 23:18

Mən klon surəti dizaynını üstün edirəm. Məqsəd aydındır.

68
17 сент. Cavab Nick 17 sentyabr verilir. 2008-09-17 03:13 '08 da 3:13 'də 2008-09-17 03:13' də

Bütün ictimai xüsusiyyətlərini kopyalamaq üçün sadə uzantı üsulu. Hər hansı bir obyekt üçün çalışır və sinfi [Serializable] olması tələb etmir. Başqa bir giriş səviyyəsinə qədər uzadıla bilər.

 public static void CopyTo( this object S, object T ) { foreach( var pS in S.GetType().GetProperties() ) { foreach( var pT in T.GetType().GetProperties() ) { if( pT.Name != pS.Name ) continue; ( pT.GetSetMethod() ).Invoke( T, new object[] { pS.GetGetMethod().Invoke( S, null ) } ); } }; } 
36
16 марта '11 в 14:38 2011-03-16 14:38 Cavab Konstantin Salavatov tərəfindən 16 mart 2011-ci il saat 14: 38 -də verilir

Yaxşı, Silverlight'da ICloneable istifadə edərək problemlər yaşadım, amma serializasiya ideyasını sevdim, mən XML-i sarmal edə bilərəm, buna görə də bunu etdim:

 static public class SerializeHelper { //Michael White, Holly Springs Consulting, 2009 //michael@hollyspringsconsulting.com public static T DeserializeXML<T>(string xmlData) where T:new() { if (string.IsNullOrEmpty(xmlData)) return default(T); TextReader tr = new StringReader(xmlData); T DocItms = new T(); XmlSerializer xms = new XmlSerializer(DocItms.GetType()); DocItms = (T)xms.Deserialize(tr); return DocItms == null ? default(T) : DocItms; } public static string SeralizeObjectToXML<T>(T xmlObject) { StringBuilder sbTR = new StringBuilder(); XmlSerializer xmsTR = new XmlSerializer(xmlObject.GetType()); XmlWriterSettings xwsTR = new XmlWriterSettings(); XmlWriter xmwTR = XmlWriter.Create(sbTR, xwsTR); xmsTR.Serialize(xmwTR,xmlObject); return sbTR.ToString(); } public static T CloneObject<T>(T objClone) where T:new() { string GetString = SerializeHelper.SeralizeObjectToXML<T>(objClone); return SerializeHelper.DeserializeXML<T>(GetString); } } 
28
02 дек. 02 dekabrda Michael White tərəfindən cavab verilir. 2009-12-02 20:39 '09 da 20:39 'da 2009-12-02 20:39

Əgər siz artıq ValueInjecter və ya Automapper kimi bir üçüncü tərəf proqramı istifadə edirsinizsə, belə bir şey edə bilərsiniz:

 MyObject oldObj; // The existing object to clone MyObject newObj = new MyObject(); newObj.InjectFrom(oldObj); // Using ValueInjecter syntax 

Bu üsuldan istifadə edərək, obyektlərinizdə ISerializable və ya ICloneable tətbiq edilməsinə ehtiyac yoxdur. Bu, MVC / MVVM modelinin tipik olmasıdır, buna görə də bu kimi sadə alətlər yaradılmışdır.

CodePlex'te enjektör dəyərinin dərin klonlanması üçün həll baxın.

26
15 окт. Oct 15-də Michael Cox tərəfindən verilmiş cavab 2012-10-15 20:55 '12 saat 20:55 'da 2012-10-15 20:55

Mən yalnız CloneExtensions layihəsini CloneExtensions . Bu ifadə işləmə kodunu tərtib edərək sadə tapşırıq əməliyyatları istifadə edərək, sürətli, dərin klon həyata keçirir.

Necə istifadə etmək olar?

Öz Clone və ya Copy üsullarını sahələr və xüsusiyyətlər arasında təyin tonu ilə yazmaq əvəzinə bir ifadə ağacından istifadə edərək özünüz üçün bir proqram hazırlayın. Bir uzantı metodu olaraq qeyd olunan GetClone<T>() metodu, sizin GetClone<T>() ilə zəng etmək üçün asanlaşdırır:

 var newInstance = source.GetClone(); 

CloningFlags enum istifadə edərək, source kopyalanması lazım olanı seçə bilərsiniz:

 var newInstance = source.GetClone(CloningFlags.Properties | CloningFlags.CollectionItems); 

Nə klonlana bilər?

  • Temel (int, uint, byte, ikiqat, char, və s.) Tanınmış dəyişkən növləri (DateTime, TimeSpan, String) və nümayəndələri (Action, Func və s. Daxil olmaqla)
  • Nullable
  • T [] serialları
  • Ümumi siniflər və strukturlar daxil olmaqla xüsusi siniflər və qurumlar.

Sinif üzvləri / strukturları daxilində klonlanır:

  • Mətn sahələri deyil, ictimai dəyərlər
  • Hər ikisini istifadə edərək, ictimai dəyərlərin dəyərləri almaq və quraşdırmaq
  • ICollection tətbiq növlər üçün kolleksiya elementləri

Necə sürətli?

GetClone<T> daha sürətlidır, çünki üzv məlumatları yalnız bir dəfə GetClone<T> bir GetClone<T> növü üçün ilk dəfə istifadə edilməlidir.

Eyni T tipli bir neçə nümunədən daha çox klon aldığınızda bir seriallaşdırma həllindən daha sürətli olur.

və daha çox ...

Dokümantasyonda oluşturulan ifadeler haqqında daha çox məlumat əldə edin.

List<int> üçün bir hata ayıklama ifadəsi hata ayıklama örneği:

 .Lambda #Lambda1<System.Func`4[System.Collections.Generic.List`1[System.Int32],CloneExtensions.CloningFlags,System.Collections.Generic.IDictionary`2[System.Type,System.Func`2[System.Object,System.Object]],System.Collections.Generic.List`1[System.Int32]]>( System.Collections.Generic.List`1[System.Int32] $source, CloneExtensions.CloningFlags $flags, System.Collections.Generic.IDictionary`2[System.Type,System.Func`2[System.Object,System.Object]] $initializers) { .Block(System.Collections.Generic.List`1[System.Int32] $target) { .If ($source == null) { .Return #Label1 { null } } .Else { .Default(System.Void) }; .If ( .Call $initializers.ContainsKey(.Constant<System.Type>(System.Collections.Generic.List`1[System.Int32])) ) { $target = (System.Collections.Generic.List`1[System.Int32]).Call ($initializers.Item[.Constant<System.Type>(System.Collections.Generic.List`1[System.Int32])] ).Invoke((System.Object)$source) } .Else { $target = .New System.Collections.Generic.List`1[System.Int32]() }; .If ( ((System.Byte)$flags  (System.Byte).Constant<CloneExtensions.CloningFlags>(Fields)) == (System.Byte).Constant<CloneExtensions.CloningFlags>(Fields) ) { .Default(System.Void) } .Else { .Default(System.Void) }; .If ( ((System.Byte)$flags  (System.Byte).Constant<CloneExtensions.CloningFlags>(Properties)) == (System.Byte).Constant<CloneExtensions.CloningFlags>(Properties) ) { .Block() { $target.Capacity = .Call CloneExtensions.CloneFactory.GetClone( $source.Capacity, $flags, $initializers) } } .Else { .Default(System.Void) }; .If ( ((System.Byte)$flags  (System.Byte).Constant<CloneExtensions.CloningFlags>(CollectionItems)) == (System.Byte).Constant<CloneExtensions.CloningFlags>(CollectionItems) ) { .Block( System.Collections.Generic.IEnumerator`1[System.Int32] $var1, System.Collections.Generic.ICollection`1[System.Int32] $var2) { $var1 = (System.Collections.Generic.IEnumerator`1[System.Int32]).Call $source.GetEnumerator(); $var2 = (System.Collections.Generic.ICollection`1[System.Int32])$target; .Loop { .If (.Call $var1.MoveNext() != False) { .Call $var2.Add(.Call CloneExtensions.CloneFactory.GetClone( $var1.Current, $flags, $initializers)) } .Else { .Break #Label2 { } } } .LabelTarget #Label2: } } .Else { .Default(System.Void) }; .Label $target .LabelTarget #Label1: } 

}

aşağıdakı C # kodu ilə eyni məna daşıyır:

 (source, flags, initializers) => { if(source == null) return null; if(initializers.ContainsKey(typeof(List<int>)) target = (List<int>)initializers[typeof(List<int>)].Invoke((object)source); else target = new List<int>(); if((flags  CloningFlags.Properties) == CloningFlags.Properties) { target.Capacity = target.Capacity.GetClone(flags, initializers); } if((flags  CloningFlags.CollectionItems) == CloningFlags.CollectionItems) { var targetCollection = (ICollection<int>)target; foreach(var item in (ICollection<int>)source) { targetCollection.Add(item.Clone(flags, initializers)); } } return target; } 

List<int> üçün öz Clone metodunuzu yazmaq kimi görünmür mu?

25
25 дек. Cavab Marcin Juraszek tərəfindən verilir 25 dekabr . 2013-12-25 01:56 '13 'da 1:56' de 2013-12-25 01:56

Qısa cavab: ICloneable interfeysini devralırsınız və sonra .clone funksiyasını yerinə yetirirsiniz. Clone, bir surəti sifariş etmək və hər hansı bir üzvün üzərinə lazımlı bir dərin surətdə yerinə yetirməlidir və nəticə obyektini qaytarmalıdır. Bu təkrarlanan bir əməliyyatdır (bu klon istədiyiniz klassın bütün üzvləri ya dəyər növləridir və ya İCloneable tətbiq edir və onların üzvləri ya dəyər növləri, ya da İCloneable və s. Həyata keçirilməsini tələb edir) tələb edir.

ICloneable istifadə edərək, klonlama haqqında daha ətraflı izahat üçün , bu yazıda .

Uzun cavab: "Bu, asılıdır". Başqalar tərəfindən qeyd edildiyi kimi, İCloneable generics tərəfindən dəstəklənmir, dərslərə dair istinadlar üçün xüsusi fikirlər tələb edir və əslində bəziları " .NET Framework " -də "səhv" kimi hesab olunur. Serializasiya metodu serializable obyektlərinizdən asılıdır və onlar nəzarət edə bilməzlər. Cəmiyyətdə hələ də "ən yaxşı" praktika olan bir çox müzakirələr var. Əslində, həllərin heç biri, əvvəlcə olaraq şərh edilən İCloneable kimi bütün vəziyyətlər üçün ən münasibdir.

Bir neçə əlavə variant (İan üçün kredit) üçün bu Corner Developer yazısına baxın.

20
17 сент. Cavab Zach Burlingame 17 sep verilir. 2008-09-17 03:14 '08 at 3:14 'da 2008-09-17 03:14

Həqiqi klonlamanın naməlum olmasını istəyirsənsə, fasttona baxa bilərsiniz.

Bu ifadəyə əsaslanan klonlama ikili serializasiyadən təxminən 10 dəfə daha sürətli işləyir və bütün obyektin bütövlüyünü saxlayır.

Bu, deməkdir ki, hiyerarşinizdə eyni obyektə bir neçə dəfə müraciət etsəniz, klonda da bir nümunə istinad olunacaq.

Klonlanmış olan obyektlərin interfeyslərinə, atributlarına və ya digər dəyişikliklərə ehtiyac yoxdur.

15
16 февр. Cavab 16 fevralda Michael Sander tərəfindən verilir . 2015-02-16 14:30 '15, saat 14:30 'da, 2015-02-16 14:30
  • Əsasən, ICloneable interfeysini tətbiq etməli, sonra da obyektin strukturunun kopyalanmasını həyata keçirməliyik.
  • Bütün üzvlərin dərin bir kopyası varsa, bütün uşaqların da klonlandığını təmin etməliyik (seçilmiş həll ilə əlaqəli deyil).
  • Bəzən bu müddətdə bir növ məhdudiyyət bilmək lazımdır, məsələn ORM obyektlərini kopyalayarsan, əksər çərçivələr bir sessiyaya əlavə olunan bir obyektə icazə verir və bu obyektin klonlaşdırılmasına ehtiyac yoxdur və ya mümkünsə, bu obyektlərin yerləşdirilməsinə diqqət yetirməliyik. sessiyaya.

Salamlar.

15
17 сент. 17 Sentyabrda dimarzionist tərəfindən verilmiş cavab . 2008-09-17 03:11 '08 at 3:11 pm 2008-09-17 03:11

Məsələn uzadılması üsulunu tətbiq etmək yaxşıdır

 public static T DeepClone<T>(this T originalObject) {  } 

və sonra hər hansı bir həll istifadə

 var copy = anyObject.DeepClone(); 

Aşağıdakı üç tətbiqə sahib ola bilərik:

Bütün əlaqədar metodlar yaxşı işləyir və dərindən sınaqdan keçirilir.

15
04 авг. cavab verildi frakon 04 aug. 2016-08-04 01:24 '16 'da 1:24 2016-08-04 01:24' də

<T> əl ilə kopyalamaq üçün . NET'in çatışmazlıqlarını aradan qaldırmaq üçün bu işə gəldim.

Mən bunu istifadə edirəm:

 static public IEnumerable<SpotPlacement> CloneList(List<SpotPlacement> spotPlacements) { foreach (SpotPlacement sp in spotPlacements) { yield return (SpotPlacement)sp.Clone(); } } 

Və başqa bir yerdə:

 public object Clone() { OrderItem newOrderItem = new OrderItem(); ... newOrderItem._exactPlacements.AddRange(SpotPlacement.CloneList(_exactPlacements)); ... return newOrderItem; } 

Bunu edən bir oneliner düşünməyə çalışdım, ancaq bu mümkün deyil, çünki çıxış anonim metod bloklarında işləmir.

Daha yaxşıdır, ümumi siyahısı <t> istifadə edin:

 class Utility<T> where T : ICloneable { static public IEnumerable<T> CloneList(List<T> tl) { foreach (T t in tl) { yield return (T)t.Clone(); } } } 
10
30 сент. Cavab 30 sentyabrda Daniel Moşmondor'a verilir 2009-09-30 12:51 '09 da 12:51 'de 2009-09-30 12:51

Başqaları ilə qeyd etdiyimiz kimi, şeyləri sadələşdirin və AutoMapper istifadə edin , bir obyektin digərinə uyğunluğu üçün sadə bir kitabxana deyil ... Bir obyektin eyni növü ilə başqa birinə kopyalamaq üçün lazım olan bütün üç satırdır:

 MyType source = new MyType(); Mapper.CreateMap<MyType, MyType>(); MyType target = Mapper.Map<MyType, MyType>(source); 

Hədəf obyekti artıq mənbə obyektinin surətidir. Yeterince asan deyil? Çözümünüzün hər yerdə istifadə ediləcək bir uzantı metodu yaradın:

 public static T Copy<T>(this T source) { T copy = default(T); Mapper.CreateMap<T, T>(); copy = Mapper.Map<T, T>(source); return copy; } 

Uzadılması metodundan istifadə edərək, üç xətt bir xətt olur:

 MyType copy = source.Copy(); 
9
28 мая '16 в 14:02 2016-05-28 14:02 cavab 28 may, '16 'da 14:02 2016-05-28 14:02 tarixində yığılmışdır

Dərin bir tətbiqdir:

 public static object CloneObject(object opSource) { //grab the type and create a new instance of that type Type opSourceType = opSource.GetType(); object opTarget = CreateInstanceOfType(opSourceType); //grab the properties PropertyInfo[] opPropertyInfo = opSourceType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); //iterate over the properties and if it has a 'set' method assign it from the source TO the target foreach (PropertyInfo item in opPropertyInfo) { if (item.CanWrite) { //value types can simply be 'set' if (item.PropertyType.IsValueType || item.PropertyType.IsEnum || item.PropertyType.Equals(typeof(System.String))) { item.SetValue(opTarget, item.GetValue(opSource, null), null); } //object/complex types need to recursively call this method until the end of the tree is reached else { object opPropertyValue = item.GetValue(opSource, null); if (opPropertyValue == null) { item.SetValue(opTarget, null, null); } else { item.SetValue(opTarget, CloneObject(opPropertyValue), null); } } } } //return the new item return opTarget; } 
8
06 сент. Cavab verilir dougajmcdonald 06 sentyabr . 2011-09-06 10:38 '11 saat 10:38 'da 2011-09-06 10:38

Ümumiyyətlə, ICloneable interfeysini həyata keçirir və özünüzü Clone tətbiq edirsiniz. C # obyektləri, bütün primitivləri yerinə yetirməkdə kömək edə bilən sadə bir surəti yerinə yetirən MemberwiseClone metoduna malikdir.

Dərin surətdə bunu avtomatik olaraq necə edəcəyini bilmək mümkün deyil.

7
17 сент. cavab HappyDude 17 sep verilir . 2008-09-17 03:09 '08 at 3:09 'da 2008-09-17 03:09

Q. Niyə bu cavabı seçməlisən?

  • Maksimum sürətin. NET olmasını istəyirsinizsə, bu cavabı seçin.
  • Həqiqətən sadə bir klonlama üsuluna ehtiyac duyarsanız bu cavabı gözdən keçirin.

Другими словами, пойти с другим ответом, если у вас нет узкого места производительности, которое требуется для исправления, и вы можете доказать это с помощью профайлера .

10 раз быстрее, чем другие методы

Следующий метод выполнения глубокого клона:

  • 10 раз быстрее, чем что-либо, что связано с сериализацией/десериализацией;
  • Довольно чертовски близко к теоретической максимальной скорости, на которую способен .NET.

И метод...

Для максимальной скорости вы можете использовать Nested MemberwiseClone, чтобы сделать глубокую копию . Его почти такая же скорость, как и копирование структуры значений, и намного быстрее, чем (а) отражение или (б) сериализация (как описано в других ответах на этой странице).

Обратите внимание, что , если вы используете Nested MemberwiseClone для глубокой копии , вам необходимо вручную реализовать ShallowCopy для каждого вложенного уровня в классе, а DeepCopy, который вызывает все сказал ShallowCopy методы для создания полного клона. Это просто: всего несколько строк, см. Демо-код ниже.

Вот результат кода, показывающий относительную разницу в производительности для 100 000 клонов:

  • 1.08 секунд для вложенных элементов-членов для вложенных структур
  • 4.77 секунд для Nested MemberwiseClone для вложенных классов
  • 39,93 секунды для сериализации/десериализации

Использование Nested MemberwiseClone в классе почти так же быстро, как копирование структуры, а копирование структуры довольно близко к теоретической максимальной скорости, на которую способен .NET.

 Demo 1 of shallow and deep copy, using classes and MemberwiseClone: Create Bob Bob.Age=30, Bob.Purchase.Description=Lamborghini Clone Bob >> BobsSon Adjust BobsSon details BobsSon.Age=2, BobsSon.Purchase.Description=Toy car Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob: Bob.Age=30, Bob.Purchase.Description=Lamborghini Elapsed time: 00:00:04.7795670,30000000 Demo 2 of shallow and deep copy, using structs and value copying: Create Bob Bob.Age=30, Bob.Purchase.Description=Lamborghini Clone Bob >> BobsSon Adjust BobsSon details: BobsSon.Age=2, BobsSon.Purchase.Description=Toy car Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob: Bob.Age=30, Bob.Purchase.Description=Lamborghini Elapsed time: 00:00:01.0875454,30000000 Demo 3 of deep copy, using class and serialize/deserialize: Elapsed time: 00:00:39.9339425,30000000 

Чтобы понять, как сделать глубокую копию, используя MemberwiseCopy, вот демонстрационный проект, который использовался для генерации времени выше:

 // Nested MemberwiseClone example. // Added to demo how to deep copy a reference class. [Serializable] // Not required if using MemberwiseClone, only used for speed comparison using serialization. public class Person { public Person(int age, string description) { this.Age = age; this.Purchase.Description = description; } [Serializable] // Not required if using MemberwiseClone public class PurchaseType { public string Description; public PurchaseType ShallowCopy() { return (PurchaseType)this.MemberwiseClone(); } } public PurchaseType Purchase = new PurchaseType(); public int Age; // Add this if using nested MemberwiseClone. // This is a class, which is a reference type, so cloning is more difficult. public Person ShallowCopy() { return (Person)this.MemberwiseClone(); } // Add this if using nested MemberwiseClone. // This is a class, which is a reference type, so cloning is more difficult. public Person DeepCopy() { // Clone the root ... Person other = (Person) this.MemberwiseClone(); // ... then clone the nested class. other.Purchase = this.Purchase.ShallowCopy(); return other; } } // Added to demo how to copy a value struct (this is easy - a deep copy happens by default) public struct PersonStruct { public PersonStruct(int age, string description) { this.Age = age; this.Purchase.Description = description; } public struct PurchaseType { public string Description; } public PurchaseType Purchase; public int Age; // This is a struct, which is a value type, so everything is a clone by default. public PersonStruct ShallowCopy() { return (PersonStruct)this; } // This is a struct, which is a value type, so everything is a clone by default. public PersonStruct DeepCopy() { return (PersonStruct)this; } } // Added only for a speed comparison. public class MyDeepCopy { public static T DeepCopy<T>(T obj) { object result = null; using (var ms = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); ms.Position = 0; result = (T)formatter.Deserialize(ms); ms.Close(); } return (T)result; } } 

Затем вызовите демо из основного:

 void MyMain(string[] args) { { Console.Write("Demo 1 of shallow and deep copy, using classes and MemberwiseCopy:\n"); var Bob = new Person(30, "Lamborghini"); Console.Write(" Create Bob\n"); Console.Write(" Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description); Console.Write(" Clone Bob >> BobsSon\n"); var BobsSon = Bob.DeepCopy(); Console.Write(" Adjust BobsSon details\n"); BobsSon.Age = 2; BobsSon.Purchase.Description = "Toy car"; Console.Write(" BobsSon.Age={0}, BobsSon.Purchase.Description={1}\n", BobsSon.Age, BobsSon.Purchase.Description); Console.Write(" Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:\n"); Console.Write(" Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description); Debug.Assert(Bob.Age == 30); Debug.Assert(Bob.Purchase.Description == "Lamborghini"); var sw = new Stopwatch(); sw.Start(); int total = 0; for (int i = 0; i < 100000; i++) { var n = Bob.DeepCopy(); total += n.Age; } Console.Write(" Elapsed time: {0},{1}\n\n", sw.Elapsed, total); } { Console.Write("Demo 2 of shallow and deep copy, using structs:\n"); var Bob = new PersonStruct(30, "Lamborghini"); Console.Write(" Create Bob\n"); Console.Write(" Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description); Console.Write(" Clone Bob >> BobsSon\n"); var BobsSon = Bob.DeepCopy(); Console.Write(" Adjust BobsSon details:\n"); BobsSon.Age = 2; BobsSon.Purchase.Description = "Toy car"; Console.Write(" BobsSon.Age={0}, BobsSon.Purchase.Description={1}\n", BobsSon.Age, BobsSon.Purchase.Description); Console.Write(" Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:\n"); Console.Write(" Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description); Debug.Assert(Bob.Age == 30); Debug.Assert(Bob.Purchase.Description == "Lamborghini"); var sw = new Stopwatch(); sw.Start(); int total = 0; for (int i = 0; i < 100000; i++) { var n = Bob.DeepCopy(); total += n.Age; } Console.Write(" Elapsed time: {0},{1}\n\n", sw.Elapsed, total); } { Console.Write("Demo 3 of deep copy, using class and serialize/deserialize:\n"); int total = 0; var sw = new Stopwatch(); sw.Start(); var Bob = new Person(30, "Lamborghini"); for (int i = 0; i < 100000; i++) { var BobsSon = MyDeepCopy.DeepCopy<Person>(Bob); total += BobsSon.Age; } Console.Write(" Elapsed time: {0},{1}\n", sw.Elapsed, total); } Console.ReadKey(); } 

Снова отметим, что , если вы используете Nested MemberwiseClone для глубокой копии , вам нужно вручную реализовать ShallowCopy для каждого вложенного уровня в классе и DeepCopy, который вызывает все упомянутые методы ShallowCopy для создания полного клона. Это просто: всего несколько строк, см. Демонстрационный код выше.

Типы значений vs. Ссылки Типы

Обратите внимание, что когда дело доходит до клонирования объекта, существует большая разница между " struct " и " классом ":

  • Если у вас есть " struct ", это тип значения , поэтому вы можете просто скопировать его, и содержимое будет клонировано (но оно будет делать только мелкие clone, если вы не используете методы в этом сообщении).
  • Если у вас есть класс , это ссылочный тип , поэтому, если вы его скопируете, все, что вы делаете, это копирование указателя на него. Чтобы создать настоящий клон, вы должны быть более креативными и использовать различия между типами значений и типами ссылок , которые создают другую копию исходного объекта в память.

См. различия между типами значений и типами ссылок .

Контрольные суммы для облегчения отладки

  • Клонирование объектов неправильно может привести к очень сложным ошибкам. В производственном коде я стараюсь реализовать контрольную сумму, чтобы дважды проверить, что объект был клонирован правильно и не был поврежден другой ссылкой на него. Эта контрольная сумма может быть отключена в режиме деблокирования.
  • Я считаю этот метод весьма полезным: часто вы хотите клонировать части объекта, а не все.

Действительно полезен для развязки многих потоков из многих других потоков

Одним из превосходных вариантов использования этого кода является подача клонов вложенного класса или структуры в очередь для реализации шаблона производителя/потребителя.

  • У нас может быть один (или более) поток, изменяющий класс, который у них есть, а затем нажатие полной копии этого класса на ConcurrentQueue .
  • Затем мы имеем один (или более) потоки, вытягивающие копии этих классов и имеющие дело с ними.

Это очень хорошо работает на практике и позволяет отделить множество потоков (производителей) от одного или нескольких потоков (потребителей).

И этот метод также близок: если мы используем вложенные структуры, это на 35 раз быстрее, чем сериализация/десериализация вложенных классов и позволяет нам использовать все потоки, доступные на машине.

Yeniləmə

По-видимому, ExpressMapper так же быстро, если не быстрее, чем ручное кодирование, например, выше. Возможно, мне придется посмотреть, как они сравниваются с профилировщиком.

7
ответ дан Contango 04 июля '15 в 20:24 2015-07-04 20:24

Я видел, как это реализовано и через отражение. В основном существует метод, который будет проходить через элементы объекта и соответствующим образом копировать их в новый объект. Когда он достиг ссылочных типов или коллекций, я думаю, что он сделал рекурсивный вызов сам по себе. Отражение стоит дорого, но оно работает очень хорошо.

7
ответ дан xr280xr 19 окт. '10 в 16:01 2010-10-19 16:01

Поскольку я не смог найти клонера, который отвечает всем моим требованиям в разных проектах, я создал глубокий клонер, который можно настроить и адаптировать к различным структурам кода вместо того, чтобы адаптировать мой код для удовлетворения требований клонеров. Это достигается путем добавления аннотаций к коду, который должен быть клонирован, или вы просто оставляете код так, как будто он имеет поведение по умолчанию. Он использует отражение, тип кэшей и основан на fasterflect . Процесс клонирования очень быстрый для огромного количества данных и высокой иерархии объектов (по сравнению с другими алгоритмами, основанными на отражении/сериализации).

https://github.com/kalisohn/CloneBehave

Также доступен как пакет nuget: https://www.nuget.org/packages/Clone.Behave/1.0.0

Например: Следующий код содержит адрес deepClone, но выполняет только мелкую копию поля _currentJob.

 public class Person { [DeepClone(DeepCloneBehavior.Shallow)] private Job _currentJob; public string Name { get; set; } public Job CurrentJob { get{ return _currentJob; } set{ _currentJob = value; } } public Person Manager { get; set; } } public class Address { public Person PersonLivingHere { get; set; } } Address adr = new Address(); adr.PersonLivingHere = new Person("John"); adr.PersonLivingHere.BestFriend = new Person("James"); adr.PersonLivingHere.CurrentJob = new Job("Programmer"); Address adrClone = adr.Clone(); //RESULT adr.PersonLivingHere == adrClone.PersonLivingHere //false adr.PersonLivingHere.Manager == adrClone.PersonLivingHere.Manager //false adr.PersonLivingHere.CurrentJob == adrClone.PersonLivingHere.CurrentJob //true adr.PersonLivingHere.CurrentJob.AnyProperty == adrClone.PersonLivingHere.CurrentJob.AnyProperty //true 
7
ответ дан kalisohn 25 янв. '16 в 20:45 2016-01-25 20:45

Этот метод решил для меня проблему:

 private static MyObj DeepCopy(MyObj source) { var DeserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace }; return JsonConvert.DeserializeObject<MyObj >(JsonConvert.SerializeObject(source), DeserializeSettings); } 

Используйте его следующим образом: MyObj a = DeepCopy(b);

6
ответ дан JerryGoyal 12 апр. '16 в 16:43 2016-04-12 16:43

Вот решение, быстрое и простое, которое сработало для меня без передачи на сериализацию/десериализацию.

 public class MyClass { public virtual MyClass DeepClone() { var returnObj = (MyClass)MemberwiseClone(); var type = returnObj.GetType(); var fieldInfoArray = type.GetRuntimeFields().ToArray(); foreach (var fieldInfo in fieldInfoArray) { object sourceFieldValue = fieldInfo.GetValue(this); if (!(sourceFieldValue is MyClass)) { continue; } var sourceObj = (MyClass)sourceFieldValue; var clonedObj = sourceObj.DeepClone(); fieldInfo.SetValue(returnObj, clonedObj); } return returnObj; } } 

ИЗМЕНИТЬ : требует

  using System.Linq; using System.Reflection; 

То, как я его использовал

 public MyClass Clone(MyClass theObjectIneededToClone) { MyClass clonedObj = theObjectIneededToClone.DeepClone(); } 
5
ответ дан Daniele D. 29 июля '16 в 16:44 2016-07-29 16:44

Мне нравится Copyconstructors:

  public AnyObject(AnyObject anyObject) { foreach (var property in typeof(AnyObject).GetProperties()) { property.SetValue(this, property.GetValue(anyObject)); } foreach (var field in typeof(AnyObject).GetFields()) { field.SetValue(this, field.GetValue(anyObject)); } } 

Если у вас есть что-то, что можно скопировать, добавьте их

5
ответ дан LuckyLikey 06 марта '15 в 16:48 2015-03-06 16:48

Генератор кода

Мы видели много идей от сериализации по сравнению с ручной реализацией до отражения, и я хочу предложить совершенно другой подход, используя Генератор кода CGbR , Метод сгенерированного клона - это эффективная память и процессор, а в 300 раз быстрее, чем стандартный DataContractSerializer.

Все, что вам нужно, это определение частичного класса с помощью ICloneable , а генератор делает остальные:

 public partial class Root : ICloneable { public Root(int number) { _number = number; } private int _number; public Partial[] Partials { get; set; } public IList<ulong> Numbers { get; set; } public object Clone() { return Clone(true); } private Root() { } } public partial class Root { public Root Clone(bool deep) { var copy = new Root(); // All value types can be simply copied copy._number = _number; if (deep) { // In a deep clone the references are cloned var tempPartials = new Partial[Partials.Length]; for (var i = 0; i < Partials.Length; i++) { var value = Partials[i]; value = value.Clone(true); tempPartials[i] = value; } copy.Partials = tempPartials; var tempNumbers = new List<ulong>(Numbers.Count); for (var i = 0; i < Numbers.Count; i++) { var value = Numbers[i]; tempNumbers.Add(value); } copy.Numbers = tempNumbers; } else { // In a shallow clone only references are copied copy.Partials = Partials; copy.Numbers = Numbers; } return copy; } } 

Qeyd У последней версии есть более нулевые проверки, но я оставил их для лучшего понимания.

5
ответ дан Toxantron 09 июня '16 в 23:56 2016-06-09 23:56

Я думаю, вы можете попробовать это.

 MyObject myObj = GetMyObj(); // Create and fill a new object MyObject newObj = new MyObject(myObj); //DeepClone it 
4
ответ дан Sudhanva Kotabagi 19 авг. '16 в 19:47 2016-08-19 19:47

Aşağıdakıları et:

  • Определите ISelf<T> с единственным типом Self , доступным только для чтения, который возвращает T и ICloneable<out T> , который происходит от ISelf<T> и включает в себя метод T Clone() .
  • Затем определите тип CloneBase , который реализует protected virtual generic VirtualClone casting MemberwiseClone для переданного типа.
  • Каждый производный тип должен реализовывать VirtualClone , вызывая метод базового клона, а затем делать все, что нужно сделать, чтобы правильно клонировать те аспекты производного типа, которые родительский метод VirtualClone еще не обработал.

Для максимальной универсальности наследования классы, демонстрирующие функциональность публичного клонирования, должны быть sealed , но должны быть получены из базового класса, который в противном случае идентичен, за исключением отсутствия клонирования. Вместо того, чтобы передавать переменные явного клонируемого типа, возьмите параметр типа ICloneable<theNonCloneableType> . Это позволит подпрограмме, которая ожидает, что клонированная производная от Foo будет работать с клонируемой производной от DerivedFoo , но также позволит создавать некланируемые производные от Foo .

4
ответ дан supercat 08 дек. '11 в 0:24 2011-12-08 00:24

Хорошо, есть некоторые очевидные примеры с отражением в этом сообщении, НО отражение обычно медленное, пока вы не начнете его кэшировать должным образом.

если вы будете кэшировать его правильно, иначе он будет клонировать 1000000 объектов на 4,6 сек (измеряется Watcher).

 static readonly Dictionary<Type, PropertyInfo[]> ProperyList = new Dictionary<Type, PropertyInfo[]>(); 

чем вы берете кешированные свойства или добавляете новый словарь и используете их просто

 foreach (var prop in propList) { var value = prop.GetValue(source, null); prop.SetValue(copyInstance, value, null); } 

проверка полного кода в моем сообщении в другом ответе

on123.ru.site/questions/2371/...

3
ответ дан Roma Borodov 19 дек. '15 в 11:17 2015-12-19 11:17

Я создал версию принятого ответа, которая работает как с [Serializable], так и с [DataContract]. Прошло некоторое время с тех пор, как я его написал, но если я правильно помню, [DataContract] понадобился другой сериализатор.

Требуется System, System.IO, System.Runtime.Serialization, System.Runtime.Serialization.Formatters.Binary, System.Xml;

 public static class ObjectCopier { /// <summary> /// Perform a deep Copy of an object that is marked with '[Serializable]' or '[DataContract]' /// </summary> /// <typeparam name="T">The type of object being copied.</typeparam> /// <param name="source">The object instance to copy.</param> /// <returns>The copied object.</returns> public static T Clone<T>(T source) { if (typeof(T).IsSerializable == true) { return CloneUsingSerializable<T>(source); } if (IsDataContract(typeof(T)) == true) { return CloneUsingDataContracts<T>(source); } throw new ArgumentException("The type must be Serializable or use DataContracts.", "source"); } /// <summary> /// Perform a deep Copy of an object that is marked with '[Serializable]' /// </summary> /// <remarks> /// Found on http://stackoverflow.com/questions/78536/cloning-objects-in-c-sharp /// Uses code found on CodeProject, which allows free use in third party apps /// - http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx /// </remarks> /// <typeparam name="T">The type of object being copied.</typeparam> /// <param name="source">The object instance to copy.</param> /// <returns>The copied object.</returns> public static T CloneUsingSerializable<T>(T source) { if (!typeof(T).IsSerializable) { throw new ArgumentException("The type must be serializable.", "source"); } // Don't serialize a null object, simply return the default for that object if (Object.ReferenceEquals(source, null)) { return default(T); } IFormatter formatter = new BinaryFormatter(); Stream stream = new MemoryStream(); using (stream) { formatter.Serialize(stream, source); stream.Seek(0, SeekOrigin.Begin); return (T)formatter.Deserialize(stream); } } /// <summary> /// Perform a deep Copy of an object that is marked with '[DataContract]' /// </summary> /// <typeparam name="T">The type of object being copied.</typeparam> /// <param name="source">The object instance to copy.</param> /// <returns>The copied object.</returns> public static T CloneUsingDataContracts<T>(T source) { if (IsDataContract(typeof(T)) == false) { throw new ArgumentException("The type must be a data contract.", "source"); } // ** Don't serialize a null object, simply return the default for that object if (Object.ReferenceEquals(source, null)) { return default(T); } DataContractSerializer dcs = new DataContractSerializer(typeof(T)); using(Stream stream = new MemoryStream()) { using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(stream)) { dcs.WriteObject(writer, source); writer.Flush(); stream.Seek(0, SeekOrigin.Begin); using (XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max)) { return (T)dcs.ReadObject(reader); } } } } /// <summary> /// Helper function to check if a class is a [DataContract] /// </summary> /// <param name="type">The type of the object to check.</param> /// <returns>Boolean flag indicating if the class is a DataContract (true) or not (false) </returns> public static bool IsDataContract(Type type) { object[] attributes = type.GetCustomAttributes(typeof(DataContractAttribute), false); return attributes.Length == 1; } } 
3
ответ дан Jeroen Ritmeijer 11 апр. '14 в 19:06 2014-04-11 19:06

Если ваше дерево объектов является Serializeable, вы также можете использовать что-то вроде этого

 static public MyClass Clone(MyClass myClass) { MyClass clone; XmlSerializer ser = new XmlSerializer(typeof(MyClass), _xmlAttributeOverrides); using (var ms = new MemoryStream()) { ser.Serialize(ms, myClass); ms.Position = 0; clone = (MyClass)ser.Deserialize(ms); } return clone; } 

сообщите, что это решение довольно просто, но оно не так эффективно, как другие решения.

И убедитесь, что если класс вырастет, все равно будут клонированы только те поля, которые также будут сериализованы.

3
ответ дан LuckyLikey 20 апр. '15 в 16:51 2015-04-20 16:51

Чтобы клонировать объект класса, вы можете использовать метод Object.MemberwiseClone,

просто добавьте эту функцию в свой класс:

 public class yourClass { // ... // ... public yourClass DeepCopy() { yourClass othercopy = (yourClass)this.MemberwiseClone(); return othercopy; } } 

чтобы выполнить глубокую независимую копию, просто вызовите метод DeepCopy:

 yourClass newLine = oldLine.DeepCopy(); 

надеюсь, что это поможет.

3
ответ дан Chtiwi Malek 25 апр. '14 в 12:39 2014-04-25 12:39
  • 1
  • 2

Другие вопросы по меткам или Задайте вопрос