Comment cloner une liste générique en C #?

593

J'ai une liste générique d'objets en C # et je souhaite cloner la liste. Les éléments de la liste sont clonables, mais il ne semble pas y avoir d'option à faire list.Clone().

Existe-t-il un moyen simple de contourner cela?

Fiona
la source
44
Vous devriez dire si vous cherchez une copie
complète
10
Quelles sont les copies profondes et peu profondes?
Colonel Panic
3
@orip N'est-ce pas clone()par définition une copie complète ? En C #, vous pouvez facilement passer des pointeurs avec =, pensais-je.
Chris
13
@Chris une copie superficielle copie un niveau plus profond que la copie du pointeur. Par exemple, une copie superficielle d'une liste aura les mêmes éléments, mais sera une liste différente.
orip

Réponses:

385

Vous pouvez utiliser une méthode d'extension.

static class Extensions
{
    public static IList<T> Clone<T>(this IList<T> listToClone) where T: ICloneable
    {
        return listToClone.Select(item => (T)item.Clone()).ToList();
    }
}
ajm
la source
71
Je pense que List.ConvertAll pourrait le faire plus rapidement, car il peut pré-allouer le tableau entier pour la liste, au lieu d'avoir à redimensionner tout le temps.
MichaelGG
2
@MichaelGG, que se passe-t-il si vous ne voulez pas convertir, mais simplement cloner / dupliquer les éléments de la liste? Est-ce que cela fonctionnerait? || var clonedList = ListOfStrings.ConvertAll (p => p);
IbrarMumtaz
29
@IbrarMumtaz: C'est la même chose que var clonedList = new List <string> (ListOfStrings);
Brandon Arnold,
4
Bonne solution! Soit dit en passant, je préfère la liste statique publique <T> CLone <T> ... Elle est plus utile dans des cas comme celui-ci, car aucune conversion supplémentaire n'est nécessaire: List <MyType> cloned = listToClone.Clone ();
Plutoz
2
c'est du clonage profond
George Birbilis
513

Si vos éléments sont des types de valeur, vous pouvez simplement faire:

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

Cependant, s'il s'agit de types de référence et que vous souhaitez une copie complète (en supposant que vos éléments soient correctement implémentés ICloneable), vous pouvez faire quelque chose comme ceci:

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

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

De toute évidence, remplacez ICloneableles génériques ci-dessus et effectuez un cast avec le type d'élément implémenté ICloneable.

Si votre type d'élément ne prend pas en charge ICloneablemais a un constructeur de copie, vous pouvez le faire à la place:

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

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

Personnellement, j'éviterais en ICloneableraison de la nécessité de garantir une copie complète de tous les membres. Au lieu de cela, je suggère le constructeur de copie ou une méthode d'usine comme YourType.CopyFrom(YourType itemToCopy)celle-ci renvoie une nouvelle instance de YourType.

Chacune de ces options peut être encapsulée par une méthode (extension ou autre).

Jeff Yates
la source
1
Je pense que List <T> .ConvertAll pourrait être plus agréable que de créer une nouvelle liste et de faire un foreach + add.
MichaelGG
2
@Dimitri: Non, ce n'est pas vrai. Le problème est que, lorsqu'elle a ICloneableété définie, la définition n'a jamais indiqué si le clone était profond ou peu profond, vous ne pouvez donc pas déterminer quel type d'opération de clonage sera effectué lorsqu'un objet l'implémentera. Cela signifie que si vous voulez faire un clone profond de List<T>, vous devrez le faire sans ICloneableêtre sûr qu'il s'agit d'une copie complète.
Jeff Yates
5
Pourquoi ne pas utiliser la méthode AddRange? ( newList.AddRange(oldList.Select(i => i.Clone())ou newList.AddRange(oldList.Select(i => new YourType(i))
phoog
5
@phoog: Je pense que c'est un peu moins lisible / compréhensible lors de la numérisation du code, c'est tout. La lisibilité gagne pour moi.
Jeff Yates
1
@JeffYates: Une ride insuffisamment prise en compte est que les choses n'ont généralement besoin d'être copiées que s'il existe un chemin d'exécution qui les muterait. Il est très courant que les types immuables contiennent une référence à une instance de type mutable, mais n'exposez jamais cette instance à rien qui la muterait. La copie inutile de choses qui ne changeront jamais peut parfois être une perte de performance majeure , augmentant l'utilisation de la mémoire par ordre de grandeur.
supercat
84

Pour une copie superficielle, vous pouvez utiliser à la place la méthode GetRange de la classe List générique.

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

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

Tiré de: Recettes génériques

Anthony Potts
la source
43
Vous pouvez également y parvenir en utilisant le constructeur de la liste <T> pour spécifier une liste <T> à partir de laquelle copier. par exemple var shallowClonedList = new List <MyObject> (originalList);
Arkiliknam
9
J'utilise souvent List<int> newList = oldList.ToList(). Même effet. Cependant, la solution d'Arkiliknam est la meilleure pour la lisibilité à mon avis.
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;
}

C'est une façon de le faire avec C # et .NET 2.0. Votre objet doit l'être [Serializable()]. Le but est de perdre toutes les références et d'en construire de nouvelles.

Patrick Desjardins
la source
11
+1 - j'aime cette réponse - elle est rapide, sale, méchante et très efficace. J'ai utilisé Silverlight et utilisé le DataContractSerializer car le BinarySerializer n'était pas disponible. Qui a besoin d'écrire des pages de code de clonage d'objet alors que vous pouvez le faire? :)
slugster
3
J'aime ça. Bien qu'il soit agréable de faire les choses "correctement", rapide et sale est souvent utile.
Odrade
3
Rapide! mais: pourquoi sale?
raiserle
2
Ce clone profond et est rapide et facile. Attention aux autres suggestions sur cette page. J'en ai essayé plusieurs et ils ne clonent pas profondément.
RandallTo
2
Le seul aspect négatif, si vous pouvez l'appeler ainsi, est que vos classes doivent être marquées Sérialisable pour que cela fonctionne.
Tuukka Haapaniemi le
30

Pour cloner une liste, il suffit d'appeler .ToList (). Cela crée une copie superficielle.

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 }
> 
Xavier John
la source
3
Solution la plus simple de loin
curveorzos
29
Un petit avertissement c'est une copie superficielle ... Cela créera deux objets de liste, mais les objets à l'intérieur seront les mêmes. C'est-à-dire que changer une propriété changera le même objet / propriété dans la liste d'origine.
Mark G
22

Après une légère modification, vous pouvez également cloner:

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;
}
Ajith
la source
N'oubliez pas que le T doit être sérialisable, sinon vous obtenez System.Runtime.Serialization.SerializationException.
Bence Végert
Bonne réponse. Un conseil: vous pouvez ajouter if (!obj.GetType().IsSerializable) return default(T);comme première instruction, ce qui empêche l'exception. Et si vous le changez en méthode d'extension, vous pouvez même utiliser l'opérateur Elvis comme var b = a?.DeepClone();(donné var a = new List<string>() { "a", "b" }; par exemple).
Matt
15

Sauf si vous avez besoin d'un clone réel de chaque objet à l'intérieur de votre List<T>, la meilleure façon de cloner une liste est de créer une nouvelle liste avec l'ancienne liste comme paramètre de collection.

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

Des modifications myListtelles que l'insertion ou la suppression n'affecteront pascloneOfMyList et vice versa.

Les objets réels que contiennent les deux listes sont cependant toujours les mêmes.

Jader Feijo
la source
Je suis d'accord avec l'utilisateur 49126, je constate qu'il s'agit d'une copie superficielle et les modifications apportées à une liste se reflètent dans l'autre liste.
Seidleroni
1
@Seidleroni, vous vous trompez. Les modifications apportées à la liste sont affectées sur l'autre liste, les modifications dans la liste elle-même ne le sont pas.
Wellington Zanelli
Ceci est une copie superficielle.
Elliot Chen
Comment est-ce une copie superficielle?
mko
2
@WellingtonZanelli vient de confirmer que la suppression d'un élément de myList le supprime également de cloneOfMyList.
Nick Gallimore
13

Utiliser AutoMapper (ou la bibliothèque de mappage que vous préférez) pour cloner est simple et très facile à gérer.

Définissez votre cartographie:

Mapper.CreateMap<YourType, YourType>();

Faites la magie:

YourTypeList.ConvertAll(Mapper.Map<YourType, YourType>);
Derek Liang
la source
13

Si vous ne vous souciez que des types de valeur ...

Et vous connaissez le type:

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

Si vous ne connaissez pas le type auparavant, vous aurez besoin d'une fonction d'assistance:

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

Le juste:

List<string> myNewList = Clone(myOldList);
James Curran
la source
15
Cela ne clone pas les éléments.
Jeff Yates
10

Si vous avez déjà référencé Newtonsoft.Json dans votre projet et que vos objets sont sérialisables, vous pouvez toujours utiliser:

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

Ce n'est peut-être pas le moyen le plus efficace de le faire, mais à moins que vous ne le fassiez des centaines de milliers de fois, vous ne remarquerez peut-être même pas la différence de vitesse.

ProfNimrod
la source
4
Il ne s'agit pas de la différence de vitesse, c'est de la lisibilité. Si je venais à cette ligne de code, je me giflerais la tête et me demanderais pourquoi ils ont introduit une bibliothèque tierce pour sérialiser puis désérialiser un objet dont je n'aurais aucune idée pourquoi cela se produit. De plus, cela ne fonctionnerait pas pour une liste de modèles avec des objets qui ont une structure circulaire.
Jonathon Cwik
1
Ce code a parfaitement fonctionné pour moi pour le clonage en profondeur. L'application migre le passe-partout de document de Dev à QA vers Prod. Chaque objet est un paquet de plusieurs objets de modèle de document, et chaque document à son tour est composé d'une liste d'objets de paragraphe. Ce code m'a permis de sérialiser les objets "source" .NET et de les désérialiser immédiatement en de nouveaux objets "cibles", qui sont ensuite enregistrés dans une base de données SQL dans un environnement différent. Après des tonnes de recherches, j'ai trouvé beaucoup de choses, dont beaucoup étaient trop lourdes, et j'ai décidé d'essayer. Cette approche courte et flexible était "juste ce qu'il fallait"!
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;
}
pratik
la source
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;
  }
}
Peter
la source
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;
        }
    }
shahrooz.bazrafshan
la source
3

Mon ami Gregor Martinovic et moi avons trouvé cette solution simple en utilisant un sérialiseur JavaScript. Il n'est pas nécessaire de marquer les classes comme sérialisables et dans nos tests en utilisant Newtonsoft JsonSerializer encore plus rapidement qu'en utilisant BinaryFormatter. Avec des méthodes d'extension utilisables sur chaque objet.

Option standard .NET JavascriptSerializer:

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

    string json = js.Serialize(value);

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

Option plus rapide avec Newtonsoft JSON :

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

    return JsonConvert.DeserializeObject<T>(json);
}
FH
la source
2
Les membres privés ne sont pas clonés à l'aide de la méthode JSON. stackoverflow.com/a/78612/885627
himanshupareek66
3
 //try this
 List<string> ListCopy= new List<string>(OldList);
 //or try
 List<T> ListCopy=OldList.ToList();
Steve
la source
3

Je serai chanceux si quelqu'un lit jamais ceci ... mais afin de ne pas retourner une liste d'objets type dans mes méthodes Clone, j'ai créé une interface:

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

Ensuite, j'ai spécifié l'extension:

public static List<T> Clone<T>(this List<T> listToClone) where T : IMyCloneable<T>
{
    return listToClone.Select(item => (T)item.Clone()).ToList();
}

Et voici une implémentation de l'interface dans mon logiciel de marquage A / V. Je voulais que ma méthode Clone () retourne une liste de VidMark (tandis que l'interface ICloneable voulait que ma méthode retourne une liste d'objets):

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();
    }
}

Et enfin, l'utilisation de l'extension à l'intérieur d'une classe:

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

//Other methods instantiate and fill the lists

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

Quelqu'un l'aime? Des améliorations?

John Kurtz
la source
2

Vous pouvez également simplement convertir la liste en un tableau à l'aide ToArray, puis cloner le tableau à l'aide Array.Clone(...). Selon vos besoins, les méthodes incluses dans la classe Array peuvent répondre à vos besoins.

JHaps
la source
Cela ne fonctionne pas; les modifications apportées aux valeurs du tableau cloné TOUJOURS modifier les valeurs de la liste d'origine.
Bernoulli Lizard
vous pouvez utiliser var clonedList = ListOfStrings.ConvertAll (p => p); comme indiqué par @IbrarMumtaz .... Fonctionne efficacement ... Les modifications apportées à une liste sont conservées pour elles-mêmes et ne doivent pas se refléter dans une autre
zainul
2

Vous pouvez utiliser la méthode d'extension:

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;
        }
   };

}

Vous pouvez cloner tous les objets en utilisant leurs membres de type valeur par exemple, considérez cette classe:

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 
    }
};

Remarque: si vous effectuez des modifications sur la copie (ou le clonage), cela n'affectera pas l'objet d'origine.

Furkan Katı
la source
2

Si vous avez besoin d'une liste clonée avec la même capacité, vous pouvez essayer ceci:

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

J'ai créé moi-même une extension qui convertit ICollection d'éléments qui n'implémentent pas 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();
    }
}
Kamil Budziewski
la source
semble que certaines collections (par exemple SelectedItems de DataGrid chez Silverlight) sautent l'implémentation de CopyTo qui est un problème avec cette approche
George Birbilis
1

J'utilise automapper pour copier un objet. Je viens de configurer un mappage qui mappe un objet sur lui-même. Vous pouvez terminer cette opération comme vous le souhaitez.

http://automapper.codeplex.com/

Dan H
la source
1

L'utilisation d'un casting peut être utile, dans ce cas, pour une copie superficielle:

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

appliqué à la liste générique:

List<T> Clone<T>(List<T> argument) => (List<T>)CloneList(argument);
Thomas Cerny
la source
1

Pour une copie complète, ICloneable est la bonne solution, mais voici une approche similaire à ICloneable utilisant le constructeur au lieu de l'interface 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();

vous aurez besoin de la bibliothèque suivante où vous faites la copie

using System.Linq

vous pouvez également utiliser une boucle for au lieu de System.Linq, mais Linq la rend concise et propre. De même, vous pouvez faire comme d'autres réponses l'ont suggéré et créer des méthodes d'extension, etc., mais rien de tout cela n'est nécessaire.

ztorstri
la source
C'est ce qu'on appelle un "constructeur de copie". C'est une approche sujette aux erreurs, chaque fois que vous ajoutez un nouveau champ à Student, vous devez vous rappeler de l'ajouter au constructeur de copie. L'idée principale derrière "clone" est d'éviter ce problème.
kenno
2
Même avec ICloneable, vous devez avoir une méthode "Clone" sur votre classe. À moins que vous n'utilisiez la réflexion (que vous pourriez également utiliser dans l'approche ci-dessus), cette méthode de clonage ressemblera beaucoup à l'approche du constructeur de copie ci-dessus et souffrira du même problème de mise à jour pour les champs nouveaux / modifiés. Mais cela veut dire "La classe doit être mise à jour lorsque les champs de la classe changent". Bien sûr que
oui
0

Le code suivant doit être transféré sur une liste avec un minimum de modifications.

Fondamentalement, cela fonctionne en insérant un nouveau nombre aléatoire à partir d'une plus grande plage avec chaque boucle successive. S'il existe déjà des nombres qui sont identiques ou supérieurs à lui, déplacez ces nombres aléatoires d'un pour qu'ils soient transférés dans la nouvelle gamme plus large d'index aléatoires.

// 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;
}
Adam Lewis
la source
0

Autre chose: vous pouvez utiliser la réflexion. Si vous le cachez correctement, il clonera 1 000 000 d'objets en 5,6 secondes (malheureusement, 16,4 secondes avec des objets internes).

[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;
    }

Je l'ai mesuré d'une manière simple, en utilisant la classe 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;

RÉSULTAT: avec l'objet interne PersonInstance - 16.4, PersonInstance = null - 5.6

CopyFactory est juste ma classe de test où j'ai une douzaine de tests, y compris l'utilisation de l'expression. Vous pouvez l'implémenter sous une autre forme dans une extension ou autre. N'oubliez pas la mise en cache.

Je n'ai pas encore testé la sérialisation, mais je doute d'une amélioration avec un million de classes. Je vais essayer quelque chose de rapide protobuf / newton.

PS: par souci de simplicité de lecture, je n'ai utilisé ici que la propriété automatique. Je pourrais mettre à jour avec FieldInfo, ou vous devriez facilement l'implémenter par vous-même.

J'ai récemment testé le sérialiseur Protocol Buffers avec la fonction DeepClone prête à l'emploi. Il gagne avec 4,2 secondes sur un million d'objets simples, mais en ce qui concerne les objets intérieurs, il gagne avec le résultat 7,4 secondes.

Serializer.DeepClone(personList);

RÉSUMÉ: Si vous n'avez pas accès aux cours, cela vous aidera. Sinon, cela dépend du nombre d'objets. Je pense que vous pouvez utiliser la réflexion jusqu'à 10 000 objets (peut-être un peu moins), mais pour plus que cela, le sérialiseur Protocol Buffers fonctionnera mieux.

Roma Borodov
la source
0

Il existe un moyen simple de cloner des objets en C # à l'aide d'un sérialiseur et désérialiseur JSON.

Vous pouvez créer une classe d'extension:

using Newtonsoft.Json;

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

Pour cloner et objecter:

obj clonedObj = originalObj.jsonCloneObject;
Albert Arnau
la source