web-dev-qa-db-fra.com

C # comment assigner la liste <T> sans être une référence?

Par exemple

List<string> name_list1 = new List<string>();
List<string> name_list2 = new List<string>();

plus tard dans le code:

name_list1.Add("McDonald");
name_list1.Add("Harveys");
name_list1.Add("Wendys");

name_list2 = name_list1; // I make a copy of namelist1 to namelist2

Donc, à partir de ce moment, j'aimerais continuer à ajouter des éléments ou à apporter des modifications à name_list2 sans affecter name_list1. Comment je fais ça?

42
TheScholar
name_list2 = new List<string>(name_list1);

Cela va cloner la liste.

97
Inisheer
name_list2 = new List<string>(name_list1); // Clone list into a different object

À ce stade, les deux listes sont des objets différents. Vous pouvez ajouter des éléments à list2 sans affecter list1

7
Dmitry Frenkel

Le problème est la mission. Jusqu'à l'affectation name_list2 = name_list1;, vous avez deux objets List différents sur le segment de mémoire pointé par les variables name_list1 et name_list2. Vous remplissez name_list1, ce qui est bien. Mais l'affectation dit, "faire name_list2 pointer le même objet sur le tas que name_list1". La liste à laquelle name_list2 faisait référence n'est plus accessible et sera récupérée. Ce que vous voulez vraiment, c'est copier le contenu de name_list1 dans name_list2. Vous pouvez le faire avec List.AddRange . Notez que cela produira une copie "superficielle", ce qui convient parfaitement pour l'exemple cité, où le contenu de la liste est constitué de chaînes, mais qui risque de ne pas être ce que vous souhaitez lorsque les membres de la liste sont des objets plus complexes. Tout dépend de vos besoins.

5
adv12

Une autre option est: Deep Cloning

public static T DeepCopy<T>(T item)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            formatter.Serialize(stream, item);
            stream.Seek(0, SeekOrigin.Begin);
            T result = (T)formatter.Deserialize(stream);
            stream.Close();
            return result;
        }

alors,

vous pouvez utiliser :

name_list2 = DeepCopy<List<string>>(name_list1);

OU:

name_list2 = DeepCopy(name_list1); 

travaillera également.

4
ayc

J'aime linq pour ça ...

Si les éléments de la liste sont des primitives ou des structures, alors ...

L2 = L1.ToList()

Si les éléments de la liste sont des classes, alors ...

L2 = L1.Select(x => x.Copy()).ToList();

Copy pourrait simplement être une exposition de MemberWiseClone copie peu profonde, ou pourrait être une implémentation d'une copie profonde.

2
u8it

Voici une solution alternative:

    List<string> name_list1 = new List<string>();
    List<string> name_list2 = new List<string>();

    name_list1.Add("McDonald");
    name_list1.Add("Harveys");
    name_list1.Add("Wendys");

    name_list2.AddRange(name_list1.ToArray());

La méthode ToArray () copie 'name_list1' dans un nouveau tableau, que nous ajoutons ensuite à name_list2 via la méthode AddRange ().

2
A.Clymer

Pour les types primitifs, vous pouvez faire ceci: 

List<string> CopyList = new List<string>(OriginalList);

Pour les types non primitifs/définis par l'utilisateur, vous pouvez le faire:

List<Person> CopyList = new List<Person>();
foreach(var item in OriginalList)
{
    CopyList.Add(new Person { 
            Name = item.Name,
            Address = item.Address
    });
}
1
davinceleecode

Je préfère la méthode de conversion Json pour la sérialisation et la désérialisation. Ainsi, vous n'avez pas à marquer les classes pour la sérialisation, en particulier si vous avez de nombreuses classes filles.

https://www.newtonsoft.com/json/help/html/SerializingJSON.htm

1
Mrunal Brahmbhatt

Si les deux listes sont du même type complexe, vous pouvez faire comme ci-dessous: -

SomeClass List2 = new List ();

List1.ForEach (u => List2.Add (u));

Ce que je fais est de parcourir en boucle chaque élément de List1 et de continuer à l'ajouter à List2 .

0
ASHWANI KUMAR

Pour les types primitifs:
List ClonedList = nouvelle liste (OriginalList);

Pour les types non primitifs/définis par l'utilisateur:
Nous devons effectuer une copie complète: Deep Copy est utilisé pour créer une copie complète complète des types de référence internes; pour cela, nous devons configurer l'objet renvoyé par MemberwiseClone ().

Étape 1 - Dans votre classe, héritez de ICloneable:
public class MyClass: ICloneable

Step2- Méthode implémenter 

public MyClass Clone()
{
  MyClass MyClassObj =new MyClass();
  MyClassObj.Property1 = this.Property1;
  .
  .
  MyClassObj.Property_N = this.Property_N;
  return MyClass;
}

Étape 3 - maintenant, clonez votre liste

List<MyClass> MyClassClone = new List<MyClass>(); 
for(i=0; i<Count; i++)
  {
      MyClassClone.Add(OriginalClaaObj[i].Clone());
  }

Cela fera une copie profonde de chaque élément de l'objet.

0
Palash Roy