Jak sklonować ogólną listę w C #?


592

Mam ogólną listę obiektów w C # i chcę sklonować listę. Elementy na liście można klonować, ale wydaje się, że nie ma takiej możliwości list.Clone().

Czy jest na to łatwy sposób?


44
Powinieneś powiedzieć, jeśli szukasz głębokiej lub płytkiej kopii
orip

10
Co to są głębokie i płytkie kopie?
Pułkownik Panic


3
@orip Czy clone()z definicji nie jest głęboką kopią? Pomyślałem, że w C # można łatwo przekazywać wskaźniki za pomocą =.
Chris

13
@Chris płytka kopia kopiuje o jeden poziom głębiej niż kopia wskazująca. Np. Płytka kopia listy będzie miała te same elementy, ale będzie inną listą.
oriP

Odpowiedzi:


385

Możesz użyć metody rozszerzenia.

static class Extensions
{
    public static IList<T> Clone<T>(this IList<T> listToClone) where T: ICloneable
    {
        return listToClone.Select(item => (T)item.Clone()).ToList();
    }
}

71
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:

List<YourType> newList = new List<YourType>(oldList);

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:

List<ICloneable> oldList = new List<ICloneable>();
List<ICloneable> newList = new List<ICloneable>(oldList.Count);

oldList.ForEach((item) =>
    {
        newList.Add((ICloneable)item.Clone());
    });

Oczywiście zamień ICloneablepowyższe elementy ogólne i użyj dowolnego typu elementu, który się implementuje ICloneable.

Jeśli twój typ elementu nie obsługuje, ICloneableale ma konstruktor kopii, możesz to zrobić w zamian:

List<YourType> oldList = new List<YourType>();
List<YourType> newList = new List<YourType>(oldList.Count);

oldList.ForEach((item)=>
    {
        newList.Add(new YourType(item));
    });

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).


1
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.

List<int> oldList = new List<int>( );
// Populate oldList...

List<int> newList = oldList.GetRange(0, oldList.Count);

Cytat z: Przepisy ogólne


43
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
public static object DeepClone(object obj) 
{
  object objResult = null;
  using (MemoryStream  ms = new MemoryStream())
  {
    BinaryFormatter  bf =   new BinaryFormatter();
    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.


11
+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.62116
Loading context from 'CSharpInteractive.rsp'.
Type "#help" for more information.
> var x = new List<int>() { 3, 4 };
> var y = x.ToList();
> x.Add(5)
> x
List<int>(3) { 3, 4, 5 }
> y
List<int>(2) { 3, 4 }
> 

3
Jak dotąd
najprostsze

28
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ć:

public static T DeepClone<T>(T obj)
{
    T objResult;
    using (MemoryStream ms = new MemoryStream())
    {
        BinaryFormatter bf = new BinaryFormatter();
        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.

List<T> myList = ...;
List<T> cloneOfMyList = new List<T>(myList);

Zmiany, myListtakie jak wstawianie lub usuwanie, nie będą miały wpływu cloneOfMyListi odwrotnie.

Rzeczywiste obiekty, które zawierają dwie listy, są jednak nadal takie same.


Zgadzam się z użytkownikiem 49126, widzę, że jest to płytka kopia, a zmiany dokonane na jednej liście są odzwierciedlone na drugiej liście.
Seidleroni,

1
@Seidleroni, mylisz się. Zmiany wprowadzone w liście są zmieniane na drugiej liście, zmiany na samej liście nie są.
Wellington Zanelli,

To jest płytka kopia.
Elliot Chen

Jak to jest płytka kopia?
mko

2
@WellingtonZanelli Właśnie potwierdził, że usunięcie elementu z myList usuwa go również z cloneOfMyList.
Nick Gallimore,

13

Użyj AutoMapper (lub dowolnej innej biblioteki mapowania), aby sklonować jest proste i łatwe w utrzymaniu.

Zdefiniuj swoje mapowanie:

Mapper.CreateMap<YourType, YourType>();

Czy magię:

YourTypeList.ConvertAll(Mapper.Map<YourType, YourType>);

13

Jeśli zależy Ci tylko na typach wartości ...

I znasz typ:

List<int> newList = new List<int>(oldList);

Jeśli nie znasz tego typu wcześniej, potrzebujesz funkcji pomocnika:

List<T> Clone<T>(IEnumerable<T> oldList)
{
    return newList = new List<T>(oldList);
}

Sprawiedliwy:

List<string> myNewList = Clone(myOldList);

15
To nie klonuje elementów.
Jeff Yates,

10

Jeśli w swoim projekcie odwoływałeś się już do Newtonsoft.Json, a Twoje obiekty można serializować, zawsze możesz użyć:

List<T> newList = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(listToCopy))

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.


4
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”!
Developer63

3
public static Object CloneType(Object objtype)
{
    Object lstfinal = new Object();

    using (MemoryStream memStream = new MemoryStream())
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
        binaryFormatter.Serialize(memStream, objtype); memStream.Seek(0, SeekOrigin.Begin);
        lstfinal = binaryFormatter.Deserialize(memStream);
    }

    return lstfinal;
}

3
public class CloneableList<T> : List<T>, ICloneable where T : ICloneable
{
  public object Clone()
  {
    var clone = new List<T>();
    ForEach(item => clone.Add((T)item.Clone()));
    return clone;
  }
}

3
    public List<TEntity> Clone<TEntity>(List<TEntity> o1List) where TEntity : class , new()
    {
        List<TEntity> retList = new List<TEntity>();
        try
        {
            Type sourceType = typeof(TEntity);
            foreach(var o1 in o1List)
            {
                TEntity o2 = new TEntity();
                foreach (PropertyInfo propInfo in (sourceType.GetProperties()))
                {
                    var val = propInfo.GetValue(o1, null);
                    propInfo.SetValue(o2, val);
                }
                retList.Add(o2);
            }
            return retList;
        }
        catch
        {
            return retList;
        }
    }

3

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:

public static T DeepCopy<T>(this T value)
{
    JavaScriptSerializer js = new JavaScriptSerializer();

    string json = js.Serialize(value);

    return js.Deserialize<T>(json);
}

Szybsza opcja przy użyciu Newtonsoft JSON :

public static T DeepCopy<T>(this T value)
{
    string json = JsonConvert.SerializeObject(value);

    return JsonConvert.DeserializeObject<T>(json);
}

2
Członkowie prywatni nie są klonowani przy użyciu metody JSON. stackoverflow.com/a/78612/885627
himanshupareek66

3
 //try this
 List<string> ListCopy= new List<string>(OldList);
 //or try
 List<T> ListCopy=OldList.ToList();

3

Będę szczęśliwy, jeśli ktoś to przeczyta ... ale aby nie zwracać listy obiektów typu w moich metodach klonowania, stworzyłem interfejs:

public interface IMyCloneable<T>
{
    T Clone();
}

Następnie określiłem rozszerzenie:

public static List<T> Clone<T>(this List<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):

public class VidMark : IMyCloneable<VidMark>
{
    public long Beg { get; set; }
    public long End { get; set; }
    public string Desc { get; set; }
    public int Rank { get; set; } = 0;

    public VidMark Clone()
    {
        return (VidMark)this.MemberwiseClone();
    }
}

I wreszcie użycie rozszerzenia w klasie:

private List<VidMark> _VidMarks;
private List<VidMark> _UndoVidMarks;

//Other methods instantiate and fill the lists

private void SetUndoVidMarks()
{
    _UndoVidMarks = _VidMarks.Clone();
}

Czy ktoś to lubi? Jakieś ulepszenia?


2

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
{
    public class ext
    {
        public static List<double> clone(this List<double> t)
        {
            List<double> kop = new List<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ę:

public class matrix
{
    public List<List<double>> mat;
    public int 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 so
        int 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 cloned
        return copy; // and copy of original is returned 
    }
};

Uwaga: jeśli dokonasz jakichkolwiek zmian podczas kopiowania (lub klonowania), nie wpłynie to na oryginalny obiekt.


2

Jeśli potrzebujesz sklonowanej listy o tej samej pojemności, możesz spróbować:

public static List<T> Clone<T>(this List<T> oldList)
{
    var newList = new List<T>(oldList.Capacity);
    newList.AddRange(oldList);
    return newList;
}

1

Stworzyłem dla siebie rozszerzenie, które konwertuje ICollection przedmiotów, które nie implementują IClonable

static class CollectionExtensions
{
    public static ICollection<T> Clone<T>(this ICollection<T> listToClone)
    {
        var array = new T[listToClone.Count];
        listToClone.CopyTo(array,0);
        return array.ToList();
    }
}

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

W tym przypadku pomocne może być użycie obsady w przypadku płytkiej kopii:

IList CloneList(IList list)
{
    IList result;
    result = (IList)Activator.CreateInstance(list.GetType());
    foreach (object item in list) result.Add(item);
    return result;
}

zastosowane do ogólnej listy:

List<T> Clone<T>(List<T> argument) => (List<T>)CloneList(argument);

1

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.

public class Student
{
  public Student(Student student)
  {
    FirstName = student.FirstName;
    LastName = student.LastName;
  }

  public string FirstName { get; set; }
  public string LastName { get; set; }
}

// wherever you have the list
List<Student> students;

// and then where you want to make a copy
List<Student> copy = students.Select(s => new Student(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 Usage
int[] indexes = getRandomUniqueIndexArray(selectFrom.Length, toSet.Length);

for(int i = 0; i < toSet.Length; i++)
    toSet[i] = selectFrom[indexes[i]];


private int[] getRandomUniqueIndexArray(int length, int count)
{
    if(count > length || count < 1 || length < 1)
        return new int[0];

    int[] toReturn = new int[count];
    if(count == length)
    {
        for(int i = 0; i < toReturn.Length; i++) toReturn[i] = i;
        return toReturn;
    }

    Random r = new Random();
    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;
}

0

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)]
public class Person
{
       ...
      Job JobDescription
       ...
}

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Job
{...
}

private static readonly Type stringType = typeof (string);

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

    private static readonly MethodInfo CreateCopyReflectionMethod;

    static CopyFactory()
    {
        CreateCopyReflectionMethod = typeof(CopyFactory).GetMethod("CreateCopyReflection", BindingFlags.Static | BindingFlags.Public);
    }

    public static 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)
        {
            var value = prop.GetValue(source, null);
            prop.SetValue(copyInstance,
                value != null && prop.PropertyType.IsClass && prop.PropertyType != stringType ? CreateCopyReflectionMethod.MakeGenericMethod(prop.PropertyType).Invoke(null, new object[] { value }) : value, null);
        }

        return copyInstance;
    }

Zmierzyłem to w prosty sposób, używając klasy Watcher.

 var person = new Person
 {
     ...
 };

 for (var i = 0; i < 1000000; i++)
 {
    personList.Add(person);
 }
 var watcher = new Stopwatch();
 watcher.Start();
 var copylist = personList.Select(CopyFactory.CreateCopyReflection).ToList();
 watcher.Stop();
 var elapsed = watcher.Elapsed;

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.

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.


0

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;

static class typeExtensions
{
    [Extension()]
    public static T jsonCloneObject<T>(T source)
    {
    string json = JsonConvert.SerializeObject(source);
    return JsonConvert.DeserializeObject<T>(json);
    }
}

Aby sklonować i sprzeciwić się:

obj clonedObj = originalObj.jsonCloneObject;
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.