当我将数据添加到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);
}
但这种行为正常吗?是否可以保留预先附加的列表?
类通过引用传递,List<T>
是一个类。因此,当您清除列表时,它也会清除列表2中通过引用传递的数据。请参阅列表-我传递对象还是引用?了解更多详细信息。
这将解决示例中显示的问题,并在清除list
:之前创建list
的新副本以添加到list2
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();
}
有关如何在C#中传递参数,特别是与引用类型有关的参数,请参阅Jon Skeet的C#中的参数传递。
你的变通办法不是变通办法;这是正确的做法。
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