Myślę, że List.ConvertAll może to zrobić w szybszym czasie, ponieważ może wstępnie przydzielić całą tablicę dla listy, zamiast konieczności zmiany rozmiaru przez cały czas.
MichaelGG
2
@MichaelGG, co zrobić, jeśli nie chcesz konwertować, a jedynie klonować / duplikować elementy na liście? Czy to zadziała? || var clonedList = ListOfStrings.ConvertAll (p => p);
IbrarMumtaz
29
@IbrarMumtaz: To samo co var clonedList = new List <string> (ListOfStrings);
Brandon Arnold
4
Fajne rozwiązanie! Nawiasem mówiąc, wolę publiczną statyczną Listę <T> Klonowanie <T> ... Jest to bardziej przydatne w takich przypadkach, ponieważ nie jest potrzebne dalsze przesyłanie: List <MyType> klonowane = listToClone.Clone ();
Plutoz
2
to jest głębokie klonowanie
George Birbilis
511
Jeśli twoje elementy są typami wartości, możesz po prostu:
Jeśli jednak są to typy referencyjne i potrzebujesz głębokiej kopii (zakładając, że elementy poprawnie się implementują ICloneable), możesz zrobić coś takiego:
Osobiście unikałbym ICloneableze względu na potrzebę zagwarantowania głębokiej kopii wszystkich członków. Zamiast tego sugerowałbym, że konstruktor kopii lub metoda fabryczna YourType.CopyFrom(YourType itemToCopy)taka zwraca nową instancję YourType.
Każda z tych opcji może być zawinięta metodą (rozszerzenie lub w inny sposób).
Myślę, że Lista <T> .ConvertAll może wyglądać ładniej niż tworzenie nowej listy i dodawanie foreach + add.
MichaelGG
2
@Dimitri: Nie, to nieprawda. Problem polega na tym, że kiedy ICloneablezostała zdefiniowana, definicja nigdy nie określała, czy klon był głęboki czy płytki, więc nie można ustalić, jaki typ operacji klonowania zostanie wykonany, gdy obiekt go zaimplementuje. Oznacza to, że jeśli chcesz wykonać głęboki klon List<T>, musisz to zrobić bez ICloneableupewnienia się, że jest to głęboka kopia.
Jeff Yates,
5
Dlaczego nie skorzystać z metody AddRange? ( newList.AddRange(oldList.Select(i => i.Clone())lub newList.AddRange(oldList.Select(i => new YourType(i))
phoog
5
@ phoog: Myślę, że jest to trochę mniej czytelne / zrozumiałe podczas skanowania kodu, to wszystko. Czytelność wygrywa dla mnie.
Jeff Yates,
1
@JeffYates: Jednym z niedostatecznie rozważanych zmarszczek jest to, że rzeczy trzeba kopiować tylko wtedy, gdy istnieje ścieżka wykonania, która by je zmutowała. To bardzo powszechne mieć niezmienne typy posiadają referencję do instancji zmienny typu, ale nigdy wystawiać tego wystąpienia do niczego, że będzie go mutować. Niepotrzebne kopiowanie rzeczy, które nigdy się nie zmienią, może czasami powodować znaczne obniżenie wydajności, zwiększając zużycie pamięci o rząd wielkości.
supercat
84
W przypadku płytkiej kopii można zamiast tego użyć metody GetRange ogólnej klasy List.
Możesz to również osiągnąć, używając konstruktora List <T>, aby określić List <T>, z którego chcesz kopiować. np. var shallowClonedList = new List <MyObject> (originalList);
Arkiliknam
9
Często używam List<int> newList = oldList.ToList(). Ten sam efekt. Jednak moim zdaniem rozwiązanie Arkiliknam jest najlepsze dla czytelności.
Dan Bechard,
82
publicstaticobjectDeepClone(object obj){object objResult =null;
using (MemoryStream ms =newMemoryStream()){BinaryFormatter bf =newBinaryFormatter();
bf.Serialize(ms, obj);
ms.Position=0;
objResult = bf.Deserialize(ms);}return objResult;}
Jest to jeden ze sposobów, aby to zrobić za pomocą C # i .NET 2.0. Twój obiekt musi być [Serializable()]. Celem jest utrata wszystkich referencji i zbudowanie nowych.
+1 - podoba mi się ta odpowiedź - jest szybka, brudna, wredna i bardzo skuteczna. Użyłem w Silverlight i użyłem DataContractSerializer, ponieważ BinarySerializer nie był dostępny. Kto musi pisać strony kodu klonowania obiektów, skoro możesz to zrobić? :)
slugster
3
Lubię to. Chociaż dobrze jest robić rzeczy „dobrze”, szybkie i brudne często przydają się.
Odrade,
3
Szybki! ale: Dlaczego jest brudny?
raiserle
2
To głębokie klony i jest szybkie i łatwe. Uważaj na inne sugestie na tej stronie. Próbowałem kilka i nie klonują głęboko.
RandallTo
2
Jedynym negatywnym aspektem, jeśli można to tak nazwać, jest to, że twoje klasy muszą być oznaczone jako Serializable, aby to zadziałało.
Tuukka Haapaniemi
29
Aby sklonować listę, wystarczy wywołać funkcję .ToList (). To tworzy płytką kopię.
Microsoft(R)Roslyn C# Compiler version 2.3.2.62116Loading context from'CSharpInteractive.rsp'.Type"#help"for more information.>var x =newList<int>(){3,4};>var y = x.ToList();> x.Add(5)> x
List<int>(3){3,4,5}> y
List<int>(2){3,4}>
Małe ostrzeżenie, to jest płytka kopia ... Spowoduje to utworzenie dwóch obiektów listy, ale obiekty wewnątrz będą takie same. Tj. Zmiana jednej właściwości spowoduje zmianę tego samego obiektu / właściwości na oryginalnej liście.
Mark G
22
Po niewielkiej modyfikacji możesz także sklonować:
publicstatic T DeepClone<T>(T obj){
T objResult;
using (MemoryStream ms =newMemoryStream()){BinaryFormatter bf =newBinaryFormatter();
bf.Serialize(ms, obj);
ms.Position=0;
objResult =(T)bf.Deserialize(ms);}return objResult;}
Nie zapominaj, że T powinien być możliwy do serializacji, w przeciwnym razie otrzymasz System.Runtime.Serialization.SerializationException.
Bence Végert
Dobra odpowiedź. Jedna wskazówka: Możesz dodać if (!obj.GetType().IsSerializable) return default(T);jako pierwszą instrukcję, która zapobiega wyjątkowi. A jeśli zmienisz go na metodę rozszerzenia, możesz nawet użyć operatora Elvisa jak var b = a?.DeepClone();(podany var a = new List<string>() { "a", "b" }; na przykład).
Matt
15
O ile nie potrzebujesz faktycznego klonowania każdego pojedynczego obiektu w swoim wnętrzu List<T>, najlepszym sposobem klonowania listy jest utworzenie nowej listy ze starą listą jako parametrem kolekcji.
Nie chodzi o różnicę prędkości, chodzi o czytelność. Gdybym przyszedł do tego wiersza kodu, uderzyłbym się w głowę i zastanawiałbym się, dlaczego wprowadzili bibliotekę innej firmy do serializacji, a następnie deserializują obiekt, który nie miałbym pojęcia, dlaczego tak się dzieje. Nie działałoby to również w przypadku listy modeli z obiektami o strukturze kołowej.
Jonathon Cwik
1
Ten kod działał doskonale dla mnie do głębokiego klonowania. Aplikacja migruje dokumentację z Dev do QA do Prod. Każdy obiekt jest pakietem kilku obiektów szablonów dokumentów, a każdy z nich składa się z listy obiektów akapitowych. Ten kod pozwala mi serializować obiekty „źródłowe” .NET i natychmiast deserializować je do nowych obiektów „docelowych”, które następnie są zapisywane w bazie danych SQL w innym środowisku. Po wielu badaniach znalazłem wiele rzeczy, z których wiele było zbyt kłopotliwych, i postanowiłem spróbować. To krótkie i elastyczne podejście było „w sam raz”!
Razem z moim przyjacielem Gregorem Martinoviciem opracowaliśmy to łatwe rozwiązanie za pomocą Serializatora JavaScript. Nie ma potrzeby oznaczania klas jako Serializowalnych, aw naszych testach z użyciem NewSoft JsonSerializer nawet szybciej niż przy użyciu BinaryFormatter. Z metodami rozszerzenia używanymi na każdym obiekcie.
Standardowa opcja .NET JavascriptSerializer:
publicstatic T DeepCopy<T>(this T value){JavaScriptSerializer js =newJavaScriptSerializer();string json = js.Serialize(value);return js.Deserialize<T>(json);}
Będę szczęśliwy, jeśli ktoś to przeczyta ... ale aby nie zwracać listy obiektów typu w moich metodach klonowania, stworzyłem interfejs:
publicinterfaceIMyCloneable<T>{
T Clone();}
Następnie określiłem rozszerzenie:
publicstaticList<T>Clone<T>(thisList<T> listToClone)where T :IMyCloneable<T>{return listToClone.Select(item =>(T)item.Clone()).ToList();}
A oto implementacja interfejsu w moim oprogramowaniu do znakowania A / V. Chciałem, aby moja metoda Clone () zwróciła listę VidMark (podczas gdy interfejs ICloneable chciał, aby moja metoda zwróciła listę obiektów):
privateList<VidMark>_VidMarks;privateList<VidMark>_UndoVidMarks;//Other methods instantiate and fill the listsprivatevoidSetUndoVidMarks(){_UndoVidMarks=_VidMarks.Clone();}
Możesz także po prostu przekonwertować listę na tablicę za pomocą ToArray, a następnie sklonować tablicę za pomocą Array.Clone(...). W zależności od potrzeb metody zawarte w klasie Array mogą spełnić Twoje potrzeby.
To nie działa; zmiany wartości w sklonowanej tablicy STILL zmieniają wartości na oryginalnej liście.
Bernoulli Lizard
możesz użyć var clonedList = ListOfStrings.ConvertAll (p => p); podany przez @IbrarMumtaz .... Działa skutecznie ... Zmiany w jednej liście są zachowywane dla siebie i nie odzwierciedlają się w innej
zainul
2
Możesz użyć metody rozszerzenia:
namespace extension
{publicclass ext
{publicstaticList<double> clone(thisList<double> t){List<double> kop =newList<double>();int x;for(x =0; x < t.Count; x++){
kop.Add(t[x]);}return kop;}};}
Możesz sklonować wszystkie obiekty, używając na przykład ich członków typu wartości, rozważ tę klasę:
publicclass matrix
{publicList<List<double>> mat;publicint rows,cols;public matrix clone(){// create new object
matrix copy =new matrix();// firstly I can directly copy rows and cols because they are value types
copy.rows =this.rows;
copy.cols =this.cols;// but now I can no t directly copy mat because it is not value type soint x;// I assume I have clone method for List<double>for(x=0;x<this.mat.count;x++){
copy.mat.Add(this.mat[x].clone());}// then mat is clonedreturn copy;// and copy of original is returned }};
Uwaga: jeśli dokonasz jakichkolwiek zmian podczas kopiowania (lub klonowania), nie wpłynie to na oryginalny obiekt.
wydaje się, że niektóre kolekcje (np. DataGrid's SelectedItems at Silverlight) pomijają implementację CopyTo, co stanowi problem w tym podejściu
George Birbilis
1
Korzystam z automappera, aby skopiować obiekt. Właśnie skonfigurowałem mapowanie, które mapuje jeden obiekt do siebie. Możesz owinąć tę operację w dowolny sposób.
W przypadku głębokiej kopii ICloneable jest właściwym rozwiązaniem, ale oto podobne podejście do ICloneable przy użyciu konstruktora zamiast interfejsu ICloneable.
publicclassStudent{publicStudent(Student student){FirstName= student.FirstName;LastName= student.LastName;}publicstringFirstName{get;set;}publicstringLastName{get;set;}}// wherever you have the listList<Student> students;// and then where you want to make a copyList<Student> copy = students.Select(s =>newStudent(s)).ToList();
będziesz potrzebować następującej biblioteki, w której wykonasz kopię
using System.Linq
możesz również użyć pętli for zamiast System.Linq, ale Linq sprawia, że jest zwięzły i czysty. Podobnie możesz zrobić, jak sugerują inne odpowiedzi, i stworzyć metody rozszerzenia itp., Ale żadna z nich nie jest konieczna.
Nazywa się to „konstruktorem kopii”. Jest to podejście podatne na błędy, ilekroć dodajesz nowe pole do Studenta, musisz pamiętać, aby dodać je do konstruktora kopiowania. Główną ideą „klonowania” jest unikanie tego problemu.
Kenno
2
Nawet z ICloneable musisz mieć w swojej klasie metodę „klonowania”. O ile nie użyjesz refleksji (której możesz również użyć w powyższym podejściu), ta metoda klonowania będzie wyglądać bardzo podobnie do powyższej metody konstruktora kopii i będzie cierpieć z powodu tego samego problemu z koniecznością aktualizacji dla nowych / zmienionych pól. Ale to mówi: „Klasa musi zostać zaktualizowana, gdy zmienią się pola klasy”. Oczywiście, że tak;)
ztorstri,
0
Poniższy kod należy przenieść na listę z minimalnymi zmianami.
Zasadniczo działa, wstawiając nową liczbę losową z większego zakresu przy każdej kolejnej pętli. Jeśli istnieją już liczby, które są takie same lub wyższe, przenieś te liczby losowe w górę o jeden, aby przenieść je do nowego większego zakresu indeksów losowych.
// Example Usageint[] indexes = getRandomUniqueIndexArray(selectFrom.Length, toSet.Length);for(int i =0; i < toSet.Length; i++)
toSet[i]= selectFrom[indexes[i]];privateint[] getRandomUniqueIndexArray(int length,int count){if(count > length || count <1|| length <1)returnnewint[0];int[] toReturn =newint[count];if(count == length){for(int i =0; i < toReturn.Length; i++) toReturn[i]= i;return toReturn;}Random r =newRandom();int startPos = count -1;for(int i = startPos; i >=0; i--){int index = r.Next(length - i);for(int j = startPos; j > i; j--)if(toReturn[j]>= index)
toReturn[j]++;
toReturn[i]= index;}return toReturn;}
Kolejna rzecz: możesz użyć odbicia. Jeśli odpowiednio buforujesz, to sklonuje 1 000 000 obiektów w 5,6 sekundy (niestety 16,4 sekundy z obiektami wewnętrznymi).
[ProtoContract(ImplicitFields=ImplicitFields.AllPublic)]publicclassPerson{...JobJobDescription...}[ProtoContract(ImplicitFields=ImplicitFields.AllPublic)]publicclassJob{...}privatestaticreadonlyType stringType =typeof(string);publicstaticclassCopyFactory{staticreadonlyDictionary<Type,PropertyInfo[]>ProperyList=newDictionary<Type,PropertyInfo[]>();privatestaticreadonlyMethodInfoCreateCopyReflectionMethod;staticCopyFactory(){CreateCopyReflectionMethod=typeof(CopyFactory).GetMethod("CreateCopyReflection",BindingFlags.Static|BindingFlags.Public);}publicstatic T CreateCopyReflection<T>(T source)where T :new(){var copyInstance =new T();var sourceType =typeof(T);PropertyInfo[] propList;if(ProperyList.ContainsKey(sourceType))
propList =ProperyList[sourceType];else{
propList = sourceType.GetProperties(BindingFlags.Public|BindingFlags.Instance);ProperyList.Add(sourceType, propList);}foreach(var prop in propList){varvalue= prop.GetValue(source,null);
prop.SetValue(copyInstance,value!=null&& prop.PropertyType.IsClass&& prop.PropertyType!= stringType ?CreateCopyReflectionMethod.MakeGenericMethod(prop.PropertyType).Invoke(null,newobject[]{value}):value,null);}return copyInstance;}
Zmierzyłem to w prosty sposób, używając klasy Watcher.
var person =newPerson{...};for(var i =0; i <1000000; i++){
personList.Add(person);}var watcher =newStopwatch();
watcher.Start();var copylist = personList.Select(CopyFactory.CreateCopyReflection).ToList();
watcher.Stop();var elapsed = watcher.Elapsed;
CopyFactory to tylko moja klasa testowa, w której mam kilkanaście testów, w tym użycie wyrażeń. Możesz to zaimplementować w innej formie w rozszerzeniu lub czymkolwiek. Nie zapomnij o buforowaniu.
Nie testowałem jeszcze serializacji, ale wątpię w poprawę z milionem klas. Spróbuję czegoś szybkiego protobuf / newton.
PS: dla uproszczenia czytania użyłem tu tylko właściwości automatycznej. Mógłbym zaktualizować za pomocą FieldInfo, lub powinieneś łatwo to zaimplementować samodzielnie.
Niedawno przetestowałem serializator buforów protokołu z funkcją DeepClone po wyjęciu z pudełka. Wygrywa z 4,2 sekundy na milion prostych obiektów, ale jeśli chodzi o obiekty wewnętrzne, wygrywa z wynikiem 7,4 sekundy.
Serializer.DeepClone(personList);
PODSUMOWANIE: Jeśli nie masz dostępu do zajęć, to pomoże. W przeciwnym razie zależy to od liczby obiektów. Myślę, że możesz użyć odbicia do 10 000 obiektów (może nieco mniej), ale dla więcej niż to serializator Buforów protokołów będzie działał lepiej.
Istnieje prosty sposób klonowania obiektów w języku C # przy użyciu serializatora i deserializatora JSON.
Możesz utworzyć klasę rozszerzenia:
using Newtonsoft.Json;staticclass typeExtensions
{[Extension()]publicstatic T jsonCloneObject<T>(T source){string json =JsonConvert.SerializeObject(source);returnJsonConvert.DeserializeObject<T>(json);}}
clone()
z definicji nie jest głęboką kopią? Pomyślałem, że w C # można łatwo przekazywać wskaźniki za pomocą =.Odpowiedzi:
Możesz użyć metody rozszerzenia.
źródło
Jeśli twoje elementy są typami wartości, możesz po prostu:
Jeśli jednak są to typy referencyjne i potrzebujesz głębokiej kopii (zakładając, że elementy poprawnie się implementują
ICloneable
), możesz zrobić coś takiego:Oczywiście zamień
ICloneable
powyższe elementy ogólne i użyj dowolnego typu elementu, który się implementujeICloneable
.Jeśli twój typ elementu nie obsługuje,
ICloneable
ale ma konstruktor kopii, możesz to zrobić w zamian:Osobiście unikałbym
ICloneable
ze względu na potrzebę zagwarantowania głębokiej kopii wszystkich członków. Zamiast tego sugerowałbym, że konstruktor kopii lub metoda fabrycznaYourType.CopyFrom(YourType itemToCopy)
taka zwraca nową instancjęYourType
.Każda z tych opcji może być zawinięta metodą (rozszerzenie lub w inny sposób).
źródło
ICloneable
została zdefiniowana, definicja nigdy nie określała, czy klon był głęboki czy płytki, więc nie można ustalić, jaki typ operacji klonowania zostanie wykonany, gdy obiekt go zaimplementuje. Oznacza to, że jeśli chcesz wykonać głęboki klonList<T>
, musisz to zrobić bezICloneable
upewnienia się, że jest to głęboka kopia.newList.AddRange(oldList.Select(i => i.Clone())
lubnewList.AddRange(oldList.Select(i => new YourType(i)
)W przypadku płytkiej kopii można zamiast tego użyć metody GetRange ogólnej klasy List.
Cytat z: Przepisy ogólne
źródło
List<int> newList = oldList.ToList()
. Ten sam efekt. Jednak moim zdaniem rozwiązanie Arkiliknam jest najlepsze dla czytelności.Jest to jeden ze sposobów, aby to zrobić za pomocą C # i .NET 2.0. Twój obiekt musi być
[Serializable()]
. Celem jest utrata wszystkich referencji i zbudowanie nowych.źródło
Aby sklonować listę, wystarczy wywołać funkcję .ToList (). To tworzy płytką kopię.
źródło
Po niewielkiej modyfikacji możesz także sklonować:
źródło
if (!obj.GetType().IsSerializable) return default(T);
jako pierwszą instrukcję, która zapobiega wyjątkowi. A jeśli zmienisz go na metodę rozszerzenia, możesz nawet użyć operatora Elvisa jakvar b = a?.DeepClone();
(podanyvar a = new List<string>() { "a", "b" };
na przykład).O ile nie potrzebujesz faktycznego klonowania każdego pojedynczego obiektu w swoim wnętrzu
List<T>
, najlepszym sposobem klonowania listy jest utworzenie nowej listy ze starą listą jako parametrem kolekcji.Zmiany,
myList
takie jak wstawianie lub usuwanie, nie będą miały wpływucloneOfMyList
i odwrotnie.Rzeczywiste obiekty, które zawierają dwie listy, są jednak nadal takie same.
źródło
Użyj AutoMapper (lub dowolnej innej biblioteki mapowania), aby sklonować jest proste i łatwe w utrzymaniu.
Zdefiniuj swoje mapowanie:
Czy magię:
źródło
Jeśli zależy Ci tylko na typach wartości ...
I znasz typ:
Jeśli nie znasz tego typu wcześniej, potrzebujesz funkcji pomocnika:
Sprawiedliwy:
źródło
Jeśli w swoim projekcie odwoływałeś się już do Newtonsoft.Json, a Twoje obiekty można serializować, zawsze możesz użyć:
Być może nie jest to najbardziej efektywny sposób, ale chyba że robisz to setki razy, możesz nawet nie zauważyć różnicy prędkości.
źródło
źródło
źródło
źródło
Razem z moim przyjacielem Gregorem Martinoviciem opracowaliśmy to łatwe rozwiązanie za pomocą Serializatora JavaScript. Nie ma potrzeby oznaczania klas jako Serializowalnych, aw naszych testach z użyciem NewSoft JsonSerializer nawet szybciej niż przy użyciu BinaryFormatter. Z metodami rozszerzenia używanymi na każdym obiekcie.
Standardowa opcja .NET JavascriptSerializer:
Szybsza opcja przy użyciu Newtonsoft JSON :
źródło
źródło
Będę szczęśliwy, jeśli ktoś to przeczyta ... ale aby nie zwracać listy obiektów typu w moich metodach klonowania, stworzyłem interfejs:
Następnie określiłem rozszerzenie:
A oto implementacja interfejsu w moim oprogramowaniu do znakowania A / V. Chciałem, aby moja metoda Clone () zwróciła listę VidMark (podczas gdy interfejs ICloneable chciał, aby moja metoda zwróciła listę obiektów):
I wreszcie użycie rozszerzenia w klasie:
Czy ktoś to lubi? Jakieś ulepszenia?
źródło
Możesz także po prostu przekonwertować listę na tablicę za pomocą
ToArray
, a następnie sklonować tablicę za pomocąArray.Clone(...)
. W zależności od potrzeb metody zawarte w klasie Array mogą spełnić Twoje potrzeby.źródło
Możesz użyć metody rozszerzenia:
Możesz sklonować wszystkie obiekty, używając na przykład ich członków typu wartości, rozważ tę klasę:
Uwaga: jeśli dokonasz jakichkolwiek zmian podczas kopiowania (lub klonowania), nie wpłynie to na oryginalny obiekt.
źródło
Jeśli potrzebujesz sklonowanej listy o tej samej pojemności, możesz spróbować:
źródło
Stworzyłem dla siebie rozszerzenie, które konwertuje ICollection przedmiotów, które nie implementują IClonable
źródło
Korzystam z automappera, aby skopiować obiekt. Właśnie skonfigurowałem mapowanie, które mapuje jeden obiekt do siebie. Możesz owinąć tę operację w dowolny sposób.
http://automapper.codeplex.com/
źródło
W tym przypadku pomocne może być użycie obsady w przypadku płytkiej kopii:
zastosowane do ogólnej listy:
źródło
W przypadku głębokiej kopii ICloneable jest właściwym rozwiązaniem, ale oto podobne podejście do ICloneable przy użyciu konstruktora zamiast interfejsu ICloneable.
będziesz potrzebować następującej biblioteki, w której wykonasz kopię
możesz również użyć pętli for zamiast System.Linq, ale Linq sprawia, że jest zwięzły i czysty. Podobnie możesz zrobić, jak sugerują inne odpowiedzi, i stworzyć metody rozszerzenia itp., Ale żadna z nich nie jest konieczna.
źródło
Poniższy kod należy przenieść na listę z minimalnymi zmianami.
Zasadniczo działa, wstawiając nową liczbę losową z większego zakresu przy każdej kolejnej pętli. Jeśli istnieją już liczby, które są takie same lub wyższe, przenieś te liczby losowe w górę o jeden, aby przenieść je do nowego większego zakresu indeksów losowych.
źródło
Kolejna rzecz: możesz użyć odbicia. Jeśli odpowiednio buforujesz, to sklonuje 1 000 000 obiektów w 5,6 sekundy (niestety 16,4 sekundy z obiektami wewnętrznymi).
Zmierzyłem to w prosty sposób, używając klasy Watcher.
REZULTAT: Z obiektem wewnętrznym PersonInstance - 16.4, PersonInstance = null - 5.6
CopyFactory to tylko moja klasa testowa, w której mam kilkanaście testów, w tym użycie wyrażeń. Możesz to zaimplementować w innej formie w rozszerzeniu lub czymkolwiek. Nie zapomnij o buforowaniu.
Nie testowałem jeszcze serializacji, ale wątpię w poprawę z milionem klas. Spróbuję czegoś szybkiego protobuf / newton.
PS: dla uproszczenia czytania użyłem tu tylko właściwości automatycznej. Mógłbym zaktualizować za pomocą FieldInfo, lub powinieneś łatwo to zaimplementować samodzielnie.
Niedawno przetestowałem serializator buforów protokołu z funkcją DeepClone po wyjęciu z pudełka. Wygrywa z 4,2 sekundy na milion prostych obiektów, ale jeśli chodzi o obiekty wewnętrzne, wygrywa z wynikiem 7,4 sekundy.
PODSUMOWANIE: Jeśli nie masz dostępu do zajęć, to pomoże. W przeciwnym razie zależy to od liczby obiektów. Myślę, że możesz użyć odbicia do 10 000 obiektów (może nieco mniej), ale dla więcej niż to serializator Buforów protokołów będzie działał lepiej.
źródło
Istnieje prosty sposób klonowania obiektów w języku C # przy użyciu serializatora i deserializatora JSON.
Możesz utworzyć klasę rozszerzenia:
Aby sklonować i sprzeciwić się:
źródło