J'ai une liste générique d'objets en C#, et je souhaite cloner cette liste. Les éléments de la liste peuvent être clonés, mais il ne semble pas y avoir d'option pour le faire. list.Clone()
.
Existe-t-il un moyen simple de contourner ce problème ?
J'ai une liste générique d'objets en C#, et je souhaite cloner cette liste. Les éléments de la liste peuvent être clonés, mais il ne semble pas y avoir d'option pour le faire. list.Clone()
.
Existe-t-il un moyen simple de contourner ce problème ?
Si vos éléments sont des types de valeurs, alors 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 voulez une copie profonde (en supposant que vos éléments implémentent correctement l'option ICloneable
), vous pourriez 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, il faut remplacer ICloneable
dans les génériques ci-dessus et l'utiliser avec n'importe quel type d'élément qui implémente ICloneable
.
Si votre type d'élément ne prend pas en charge ICloneable
mais possède un constructeur de copie, vous pouvez faire ceci à 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 ICloneable
en raison de la nécessité de garantir une copie profonde de tous les membres. A la place, je suggérerais le constructeur de copie ou une méthode de fabrique comme YourType.CopyFrom(YourType itemToCopy)
qui renvoie une nouvelle instance de YourType
.
Chacune de ces options peut être enveloppée par une méthode (extension ou autre).
Je pense que List<T>.ConvertAll pourrait être plus agréable que de créer une nouvelle liste et de faire un foreach+add.
Bon point. Je dois admettre que je suis encore en train de me familiariser avec tous les appels LINQ.
+1 Donc, en résumé, il est impossible de fournir une fonction de clonage profond pour une Generic.List. Est-ce bien cela ?
Je pense que List.ConvertAll pourrait le faire plus rapidement, puisqu'il peut pré-allouer le tableau entier pour la liste, au lieu de devoir le redimensionner tout le temps.
@MichaelGG, que se passe-t-il si vous ne voulez pas convertir mais juste cloner/dupliquer les éléments de la liste ? Cela fonctionnerait-il ? || var clonedList = ListOfStrings.ConvertAll(p => p) ;
Pour une copie peu profonde, vous pouvez utiliser la méthode GetRange de la classe générique List.
List<int> oldList = new List<int>( );
// Populate oldList...
List<int> newList = oldList.GetRange(0, oldList.Count);
Cité par : Recettes de génériques
Vous pouvez également réaliser ceci en utilisant le constructeur de la List<T> pour spécifier une List<T> à partir de laquelle copier. eg var shallowClonedList = new List<MyObject>(originalList) ;
J'utilise souvent List<int> newList = oldList.ToList()
. Même effet. Cependant, la solution d'Arkiliknam est la meilleure pour la lisibilité à mon avis.
public static object DeepClone(object obj)
{
object objResult = null;
using (var ms = new MemoryStream())
{
var 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 être [Serializable()]
. L'objectif est de perdre toutes les références et d'en construire de nouvelles.
+1 - j'aime cette réponse - elle est rapide, sale, méchante et très efficace. J'ai utilisé en silverlight, et j'ai utilisé le DataContractSerializer car le BinarySerializer n'était pas disponible. Qui a besoin d'écrire des pages de code de clonage d'objet quand on peut simplement faire ça ? :)
J'aime ça. Même si c'est bien de faire les choses "bien", le "vite fait bien fait" est souvent utile.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
54 votes
Vous devez dire si vous cherchez une copie profonde ou une copie superficielle.
13 votes
Que sont les copies profondes et superficielles ?
6 votes
@ColonelPanic fr.wikipedia.org/wiki/Object_copy#Shallow_copy
3 votes
@orip n'est pas
clone()
par définition une copie profonde ? En C#, on peut facilement faire circuler des pointeurs avec =, je croyais.16 votes
@Chris une copie superficielle copie un niveau plus profond que la copie pointeur. Par exemple, une copie superficielle d'une liste aura les mêmes éléments, mais sera une liste différente.
3 votes
Alors qu'une copie profonde sera une nouvelle liste, avec de nouveaux éléments, mais dont le contenu est le même.
1 votes
Vérifiez ceci Réponse : : stackoverflow.com/a/52097307/4707576 sur : Clonage d'objets sans sérialisation