Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
正在修改两个c#列表_C#_Data Structures - Fatal编程技术网

正在修改两个c#列表

正在修改两个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<

我的两个列表都被修改了,我试图避免这种行为

这里有什么问题

我有一个“大”列表,我想删除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();
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);