我的两个列表都在修改,我正试图避免这种行为......
这里有什么问题?
我有一个'大'列表,我想删除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();
答案 0 :(得分: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 + " ");
}
答案 1 :(得分:0)
您的问题是您只是引用同一个对象。 要避免此行为,您必须像这样初始化列表B:
List<string> bList = new List<string>(aList);
答案 2 :(得分: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
你提到你有一个相当大的清单。如果你的意思是数千或更少,那么juharr的答案很棒。如果列表中有数百万个项目,您可能需要重新考虑首先填充该列表的方式,并可能修改数据库查询。
答案 3 :(得分:0)
您可以使用LINQ以外:
List<int> a = new List<int>{ 1, 2 };
List<int> b = new List<int> { 2 };
var c = a.Except(b);
答案 4 :(得分: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();
这将创建原始列表的真实副本,并完成您正在寻找的行为。
答案 5 :(得分:0)
在您的代码中:
List<string> bList = aList;
不复制列表,而是复制对列表的引用。这就是为什么当您更改一个列表时,更改会反映在另一个列表中,因为它们实际上是相同的列表。
要创建新列表,您需要使用:
List<string> bList = new List<string>(aList);
有关详细信息,请参阅List参考。
另外,请确保您了解C#中值和引用类型之间的区别。分配引用类型时,只是复制引用,而在分配值类型时,则复制数据。只有原始类型,结构和枚举是C#中的值类型,其他一切都是引用类型。在您的示例中,您正在处理作为引用类型的列表对象,但您希望它的行为类似于值类型。阅读更多here。