2 votes

Modifier une nouvelle collection sans toucher à la collection originale

Mon objectif est d'obtenir une copie de la collection avec un élément spécifique retiré de celle-ci sans toucher aux éléments de la collection originale. J'ai la classe suivante :

public class Foo
{
    public string Name { get; set; }
}

et l'opération que je fais est :

 var collection = new Collection<Foo>
                         {
                             new Foo {Name = "Name1"},
                             new Foo {Name = "Name2"},
                             new Foo {Name = "Name3"},
                             new Foo {Name = "Name4"}
                         };
    var newCollection = new Collection<Foo>(collection);

    Foo f = collection.FirstOrDefault(x => x.Name == "Name2");
    if (f != null)
    {
        newCollection.Remove(f);
    }

Je supprime l'élément de "newCollection" mais le problème est que la ligne suivante :

newCollection.Remove(f);

supprime également l'élément de la collection originale, c'est-à-dire de l'objet "collection". Je veux modifier uniquement "newCollection" et non "collection". Comment puis-je le faire ? La ligne suivante ne fait-elle pas une copie profonde ?

 var newCollection = new Collection<Foo>(collection);

Si oui, pourquoi l'objet original est-il affecté ?

Je sais que je peux atteindre mon objectif grâce à cette ligne également :

var newCollection = collection.Where(x => x.Name != "Name2");

mais je suis dans un dilemme au sujet de la suppression et de la copie profonde qui se produisent ci-dessus.

3voto

Jon Skeet Points 692016

Cela est dû au comportement de la Collection<T>(IList<T>) Constructeur :

Les éléments de la liste ne sont pas copiés. La liste est enveloppée par la collection, de sorte que les modifications ultérieures des éléments de la liste sont visibles à travers la collection.

Si vous voulez une copie superficielle de la collection 1 vous pouvez utiliser List<T> à la place :

List<Foo> newCollection = new List<T>(collection);

(C'est un peu étrange de voir Collection<T> utilisé de cette façon. C'est normalement utilisé comme le base pour d'autres collections génériques).


1 Il s'agit d'une copie superficielle car elle ne fait que copier la valeur de chaque élément en tant que référence, plutôt que de cloner chaque élément. Foo objet. Si tu as écrit :

newCollection[0].Name = "Hello!";
Console.WriteLine(collection[0]);

... il imprimera toujours "Hello !". Créer une enveloppe autour d'une collection existante n'est pas vraiment créer une copie du tout, peu importe le sens. o profond.

1voto

animaonline Points 2755

Vous devez la cloner, le newCollection n'est qu'une référence à la collection originale.

0voto

Jehof Points 14720

Collection<Foo>(collection) enveloppe uniquement la collection fournie, de sorte que toute modification de la collection affecte également la collection originale.

Vous devez utiliser un List<Foo> pour faire ce que vous voulez, car le constructeur de List<T>(IEnumerable<T>) copie les valeurs de la collection originale.

var collection = new Collection<Foo>
                         {
                             new Foo {Name = "Name1"},
                             new Foo {Name = "Name2"},
                             new Foo {Name = "Name3"},
                             new Foo {Name = "Name4"}
                         };
    var newCollection = new List<Foo>(collection);

    Foo f = collection.FirstOrDefault(x => x.Name == "Name2");
    if (f != null)
    {
        newCollection.Remove(f);
    }

0voto

scartag Points 9312

Vous pourriez essayer de faire ceci à la place.

  var newCollection = new Collection<Foo>();

collection.ToList().ForEach(x => newCollection.Add(x));

Prograide.com

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.

Powered by:

X