web-dev-qa-db-fra.com

Comment faire un clone correct de la liste <MonObjet>?

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

List<MyObject> a1 = new List<MyObject>();

var new1 = a1;

Maintenant, si je change a1 puis new1 va également être modifié.

Donc ma question est de savoir comment pour faire un clone de a1 correctement?

14
Developer

Cela ne sera pas Clone chaque élément de la liste mais vous créera une nouvelle liste

var new1 = new List<MyObject>(a1);

Si vous souhaitez cloner chaque élément de la liste, vous pouvez implémenter ICloneable sur MyObject

var new1 = new List<MyObject>(a1.Select(x => x.Clone()));

EDIT: Pour le rendre un peu plus clair, les deux copient les éléments de la liste a1 dans une nouvelle liste. Il vous suffit de décider si vous souhaitez avoir de nouveaux MyObject ou conserver les originaux. Si vous souhaitez cloner MyObject, vous aurez besoin d'un moyen de les cloner, ce qui se fait généralement via ICloneable.

34
aqwert

Ou, vous pouvez faire quelque chose comme ceci:

public static class CloneClass
{
    /// <summary>
    /// Clones a object via shallow copy
    /// </summary>
    /// <typeparam name="T">Object Type to Clone</typeparam>
    /// <param name="obj">Object to Clone</param>
    /// <returns>New Object reference</returns>
    public static T CloneObject<T>(this T obj) where T : class
    {
        if (obj == null) return null;
        System.Reflection.MethodInfo inst = obj.GetType().GetMethod("MemberwiseClone",
            System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
        if (inst != null)
            return (T)inst.Invoke(obj, null);
        else
            return null;
    }
}

Ensuite, utilisez-le comme:

var new1 = CloneClass.CloneObject<List<<MyObject>>(a1);
4
MAckerman

Je pense que la pratique générale est d'éviter d'utiliser Clone car il n'est pas clair s'il s'agit d'une copie Shallow vs Deep de l'objet.

Plus d'informations à ce sujet ici: http://blogs.msdn.com/b/brada/archive/2004/05/03/125427.aspx

Une solution assez courante a été d'utiliser la classe BinaryFormatter pour sérialiser/dérialiser un objet et renvoyer la nouvelle instance, mais avec la mise en garde que la classe doit être sérialisable:

https://stackoverflow.com/a/1213649/1212407

En supposant ce qui précède, vous pourriez faire:

var clonedList = originaList.DeepClone();
1
Jesse