当我向List
添加数据时,将该列表附加到另一个列表,然后在原始列表中使用List.Clear()
,它会清空所有内容,并且已经附加的列表不会被保留。
以下是我所谈论的一个例子。可以说我制作了两个这样的列表:
List<int> list = new List<int>();
List<List<int>> list2 = new List<List<int>>();
for(int i=0;i<10;i++){
for(int i2=0;i2<10;i2++){
list.Add(i2);
}
list2.Add(list);
list.Clear();
}
当我运行list.Clear()
时,它会清除我已附加到list2
我知道解决方法是重新安排代码:
List<List<int>> list2 = new List<List<int>>();
for(int i=0;i<10;i++){
List<int> list = new List<int>(); //<- moved inside the for
for(int i2=0;i2<10;i2++){
list.Add(i2);
}
list2.Add(list);
}
但这是正常行为吗?是否可以保留预先附加的列表?
答案 0 :(得分:4)
通过引用传递类,List<T>
是一个类。因此,当您清除列表时,它还会清除list2中引用传递的数据。有关详细信息,请参阅List - do I pass objects or references?。
这应解决您的示例中显示的问题,并在清除list
之前创建list2
的新副本以添加到list
:
List<int> list = new List<int>();
List<List<int>> list2 = new List<List<int>>();
for(int i=0;i<10;i++){
for(int i2=0;i2<10;i2++){
list.Add(i2);
}
list2.Add(list.ToList()); //modified to create a new List when adding
list.Clear();
}
另请参阅Jon Skeet的Parameter passing in C#,了解有关如何在C#中传递参数的更广泛信息,尤其是与引用类型相关的信息。
答案 1 :(得分:0)
你的解决方法不是一种解决方法;这是正确的做法。
List是一个对象,因此是一个引用类型。您的list
是整数值的列表;您的list2
是对整数列表的引用列表。
调用list.ToList()
有效,因为该方法返回一个新列表。来自消息来源:
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
return new List<TSource>(source);
}
这里有一些代码来说明值类型列表与引用类型列表之间的区别:
void Main()
{
int x = 0, y = 1, z = 2;
var list = new List<int> { x, y, z };
list.ForEach(i => Console.WriteLine(i));
x = y = z = 0;
list.ForEach(i => Console.WriteLine(i));
WorseInt a = new WorseInt { Value = 0 },
b = new WorseInt { Value = 1 },
c = new WorseInt { Value = 2 };
var worseList = new List<WorseInt> { a, b, c };
worseList.ForEach(i => Console.WriteLine(i.Value));
a.Value = b.Value = c.Value = 0;
worseList.ForEach(i => Console.WriteLine(i.Value));
}
public class WorseInt
{
public int Value { get; set; }
}
输出:
0
1
2
0
1
2
0
1
2
0
0
0