2016-03-11 2 views
-1

Оба моих списка изменяются, и я стараюсь избегать такого поведения ...Изменения в обоих списках C#

Что здесь есть?

У меня есть «большой» список, и я хочу удалить все элементы, которые присутствуют в itemsToRemoveList, но без изменения исходного списка.

я упростил пример кода ..

List<string> aList = new List<string>(){"My","name","is", "jeff"}; // cached full list 

List<string> bList = aList; // initial copy 

List<string> itemsToRemoveList = new List<string>(){"jeff"}; 

bList.RemoveAll(itemsToRemoveList.Contains); // remove only from copy 

foreach (string s in aList) 
{ 
    Console.Write(s + " "); // expect "my name is jeff" 
} 
Console.WriteLine(); 
foreach (string s in bList) 
{ 
    Console.Write(s + " "); // expect "my name is" 
} 
// however this modifies both collections. 

     Console.ReadLine(); 
+2

Это не «копия», которая просто создает другую ссылку на тот же список. – juharr

+0

Вот очень полезная ссылка, которая охватывает лучший способ сделать это, если ваш список имеет тип значения или ссылочный тип: http://stackoverflow.com/questions/222598/how-do-i-clone-a-generic-list -in-c – sr28

+0

@ sr28 Что касается создания нового списка, были клонированы объекты или копии другого списка. Здесь это действительно не нужно, поскольку 'string' неизменен. – juharr

ответ

7

Когда вы

List<string> bList = aList; 

Это не создает новый список. Это просто устанавливает вашу переменную bList в ссылку, указывающую на тот же список, что и aList. Способ создания копии состоит в том, чтобы создать новый список.

List<string> bList = new List<string>(aList); 

Но если вы также хотите фильтровать значения, лучше использовать Linq.

List<string> aList = new List<string>(){"My","name","is", "jeff"}; 
List<string> itemsToRemoveList = new List<string>(){"jeff"}; 
List<string> bList = aList.Where(a => !itemsToRemoveList.Contains(a)).ToList(); 

foreach (string s in aList) 
{ 
    Console.Write(s + " "); 
} 
Console.WriteLine(); 
foreach (string s in bList) 
{ 
    Console.Write(s + " "); 
} 
0

Ваша проблема в том, что вы просто ссылаетесь на один и тот же объект. Чтобы избежать этого, вы должны инициализировать список B, как это:

List<string> bList = new List<string>(aList); 
0

Помните, что объекты в .Net ссылочные типы и при назначении одного ссылочного типа к другому, вы фактически назначая указатель на местоположение в память исходного объекта.

List<string> aList = new List<string>(){"My","name","is", "jeff"}; // cached full list 
List<string> bList = aList; // <- NOT a copy, this is assigning the same object 

Вы упомянули, что у вас есть довольно большой список. Если вы имеете в виду тысячи или меньше, то ответ Джухарра велик. Если у вас есть миллионы элементов в вашем списке, вам может потребоваться переосмыслить, как этот список был заполнен в первую очередь, и, возможно, изменить ваши запросы к базе данных.

0

Вы можете использовать LINQ кроме:

List<int> a = new List<int>{ 1, 2 }; 
List<int> b = new List<int> { 2 }; 
var c = a.Except(b); 
0

Вы получаете это поведение, потому что вы просто ссылающиеся свой первоначальный список. Ваш второй список просто указывает на тот же адрес памяти, что и ваш оригинал. Вам нужно добавить что-то вроде следующего:

List<string> aList = new List<string>() { "My", "name", "is", "jeff" }; // cached full list 

    List<string> bList = new List<string>(); 

    foreach(var item in aList) 
    { 
     bList.add(item); 
    } 

    List<string> itemsToRemoveList = new List<string>() { "jeff" }; 

    bList.RemoveAll(itemsToRemoveList.Contains); // remove only from copy 

    foreach (string s in aList) 
    { 
     Console.Write(s + " "); // expect "my name is jeff" 
    } 
     Console.WriteLine(); 
    foreach (string s in bList) 
    { 
     Console.Write(s + " "); // expect "my name is" 
    } 
    // however this modifies both collections. 

    Console.ReadLine(); 

Это позволило бы создать точную копию исходного списка и выполнить поведение, которое вы ищете.

0

В коде:

List<string> bList = aList; 

не копирует список, а скорее копирует ссылки на список. Вот почему, когда вы меняете один список, это изменение отражается в другом, поскольку они фактически являются одним и тем же списком.

Чтобы создать новый список, вам нужно использовать:

List<string> bList = new List<string>(aList); 

Посмотреть List Ссылки для получения более подробной информации.

Также убедитесь, что вы понимаете разницу между значениями и ссылочными типами в C#. Когда вы назначаете ссылочный тип, вы просто копируете ссылку, тогда как при назначении типа значения вы копируете данные. Только примитивные типы, структуры и перечисления являются типами значений в C#, все остальное является ссылочным типом. В вашем примере вы имеете дело с объектом списка, который является ссылочным типом, но вы ожидаете, что он будет вести себя как тип значения. Подробнее here.