如何在使用List.Clear()之前保留已创建的列表

时间:2014-09-18 02:47:26

标签: c# asp.net

当我向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);

}

但这是正常行为吗?是否可以保留预先附加的列表?

2 个答案:

答案 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