在 c# 中编辑列表 时出现问题

本文关键字:问题 double 编辑 列表 | 更新日期: 2023-09-27 18:35:18

我正在将 double[] 类型的列表传递给类中的函数,使用 tempList 编辑函数中的值,然后返回编辑后的值。但是正在传递的原始列表也在编辑中,我不希望它们被编辑以匹配临时列表。

这是代码。

List<double[]> newList = new List<double[]();
newList = myClass.myFunction(value, originalList);
// myClass
...
// myFunction
public List<double[]> myFunction(int value, List<double[]> myList)
{
    List<double[]> tempList = new List<double[]>();
    for (int i = 0; i < myList).Count; i++)
    {
       tempList.Add(myList[i]);
    }

    // Do stuff to edit tempList
    return tempList;
}

在 c# 中编辑列表<double[]> 时出现问题

请记住,数组是引用类型。将数组添加到 tempList 时,仅添加对该数组的引用,以便myListtempList都引用相同的double[]对象。

相反,您需要克隆数组:

for (int i = 0; i < myList.Count; i++)
{
   tempList.Add((double[])myList[i].Clone());
}
数组

here double[] 是引用类型,因此行

tempList.Add(myList[i]);

正在添加对原始数组的引用。 然后,当您编辑临时列表时,您正在编辑原始数组。 像这样复制:

tempList.Add(myList[i].ToArray());

您将对数组的引用添加到新列表中,但不复制每个数组的内容。 您的副本应如下所示:

foreach (double[] item in myList)
{
    double[] copy = new double[item.Length];
    Array.Copy(item, copy);
    templist.Add(copy);
}

您遇到的问题是double[]是引用类型,而不是值类型,因此当您将其添加到tempList时,您是在添加对原始对象的引用,而不是新对象。 在将它添加到tempList之前,您实际上需要创建一个新double[],这样您就不会处理原始对象。

假设您可以使用 LINQ,则不需要循环。 您可以执行以下操作:

var tempList = myList.Select(x => x.ToArray()).ToList();

这是因为集合/引用类型是通过引用传递的。(实际上,保持变量是按值传递的,但所有变量都指向相同的引用)。

有关详细说明,请阅读此

SO答案

如果您希望我的函数中的修改不反映在原始集合中,则必须复制/克隆它,然后传递给myFunction

newList = myClass.myFunction(value, (List<double>)originalList.Clone());
tempList.Add(myList[i]);

表示将索引 i 上的 double[] 对象的引用添加到 temp 列表。因此,如果您编辑该对象的值,您将在两个列表中都有机会。

如果你想有一个不会相互影响的不同克隆列表,你必须这样做:

List<double[]> tempList = new List<double[]>();
for (int i = 0; i < myList).Count; i++)
{
   double[] originalListItem = myList[i];
   // the most important step here!!! - clone the originalListItem to clonedListItem
   tempList.Add(clonedListItem);
}

// Do stuff to edit tempList
return tempList;

您正在将 double[] 引用复制到新列表,这是一个浅拷贝。您需要一个深层副本并创建新的双精度数组来编辑临时数组,而无需更改原始数组。

您是在 tempList 中插入对数组的引用,而不是数组的副本。因此,如果您更改 tempList 中的值,则正在更改原始数组。

这段代码会更好用:

    for (int i = 0; i < myList.Count; i++)
    {
       var copy = new Double[myList[i].Length];
       Array.Copy(myList[i], copy, myList[i].Length);
       tempList.Add(copy);
    }