正在修改两个c#列表
我的两个列表都被修改了,我试图避免这种行为 这里有什么问题 我有一个“大”列表,我想删除itemsToRemoveList中存在的所有项目,但不让它修改原始列表 我已经简化了示例代码正在修改两个c#列表,c#,data-structures,C#,Data Structures,我的两个列表都被修改了,我试图避免这种行为 这里有什么问题 我有一个“大”列表,我想删除itemsToRemoveList中存在的所有项目,但不让它修改原始列表 我已经简化了示例代码 List<string> aList = new List<string>(){"My","name","is", "jeff"}; // cached full list List<string> bList = aList; // initial copy List<
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();
List aList=new List(){“我的”、“名字”、“是”、“杰夫”};//缓存的完整列表
列表bList=aList;//原件
List itemsToRemoveList=新列表(){“jeff”};
bList.RemoveAll(itemsToRemoveList.Contains);//仅从副本中删除
foreach(列表中的字符串s)
{
Console.Write(s+“”);//应该是“我叫杰夫”
}
Console.WriteLine();
foreach(bList中的字符串s)
{
Console.Write(s+“”);//应该是“我的名字是”
}
//但是,这会修改这两个集合。
Console.ReadLine();
当您这样做时
List<string> bList = 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 + " ");
}
List aList=newlist(){“我的”、“名字”、“是”、“杰夫”};
List itemsToRemoveList=新列表(){“jeff”};
List bList=aList.Where(a=>!itemsToRemoveList.Contains(a)).ToList();
foreach(列表中的字符串s)
{
控制台。写入(s+“”);
}
Console.WriteLine();
foreach(bList中的字符串s)
{
控制台。写入(s+“”);
}
您的问题是,您只是在引用同一个对象。
为了避免这种行为,您必须如下初始化列表B:
List<string> bList = new List<string>(aList);
List bList=新列表(列表);
请记住.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
List aList=new List(){“我的”、“名字”、“是”、“杰夫”};//缓存的完整列表
列表bList=aList;// 您可以使用LINQ,但以下情况除外:
List<int> a = new List<int>{ 1, 2 };
List<int> b = new List<int> { 2 };
var c = a.Except(b);
List a=新列表{1,2};
列表b=新列表{2};
var c=a,但(b)除外;
您得到这种行为是因为您只是在引用原始列表。第二个列表只是指向与原始列表相同的内存地址。您需要添加以下内容:
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();
List aList=new List(){“我的”、“名字”、“是”、“杰夫”};//缓存的完整列表
List bList=新列表();
foreach(列表中的var项目)
{
b增加(项目);
}
List itemsToRemoveList=新列表(){“jeff”};
bList.RemoveAll(itemsToRemoveList.Contains);//仅从副本中删除
foreach(列表中的字符串s)
{
Console.Write(s+“”);//应该是“我叫杰夫”
}
Console.WriteLine();
foreach(bList中的字符串s)
{
Console.Write(s+“”);//应该是“我的名字是”
}
//但是,这会修改这两个集合。
Console.ReadLine();
这将创建原始列表的真实副本,并完成您正在寻找的行为 在您的代码中:
List<string> bList = aList;
List bList=aList;
不复制列表,而是复制对列表的引用。这就是为什么当您更改一个列表时,更改会反映在另一个列表中,因为它们实际上是同一个列表
要创建新列表,您需要使用:
List<string> bList = new List<string>(aList);
List bList=新列表(列表);
有关更多详细信息,请参阅参考资料
还要确保您了解C#中的值类型和引用类型之间的差异。分配引用类型时,您只是复制引用,而分配值类型时,您复制数据。在C#中,只有基元类型、结构和枚举是值类型,其他都是引用类型。在您的示例中,您处理的是一个引用类型的列表对象,但您希望它的行为类似于值类型。阅读更多信息。这不是一个“副本”,它只是创建对同一列表的另一个引用。这里有一个非常有用的链接,介绍了在列表为值类型或引用类型时执行此操作的最佳方法:@sr28,它处理在克隆项目或复制其他列表时创建新列表的问题。这在这里并不需要,因为string
是不可变的。
List<string> bList = new List<string>(aList);