列表<>用旧列表覆盖值

Ale*_*tic 0 c# list

我有这个代码:

List<List<string>> strs = new List<List<string>>();
List<string> str = new List<string>();

foreach (DataGridViewRow sr in dataGridView1.SelectedRows)
{
    if(i >= 10)
    {
        strs.Add(str); //Here strs have one str with 10 values
        str.Clear();
        i = 0;
        var a = strs; //Here strs have one str with 0 values
    }
    str.Add(sr.Cells["MOBILNI"].Value.ToString().Trim());
    i++;
}
strs.Add(str);
Run Code Online (Sandbox Code Playgroud)

我列出了strings我填充的列表,当它达到10个成员时,我将整个列表放入列表中List<string>,然后清除列表strings以填充下一个10项.问题是,当strings达到10个成员的列表时,我将其添加到列表中List<string>并在调试中我看到我strs有1个成员(List<string>)其中有10个元素(10个字符串)但是当我清除strings它的基本列表时它也清除了里面的列表List<List<string>>.

当我使用str = new List<string>()而不是str.Clear()它正常工作.

那为什么会发生这种情况以及如何克服它?

Him*_*ere 5

当您编写时strs.Add(str),将完全相同的实例添加List<string>到您的列表列表中,之后您将其清除.呼叫str.Clear将因此被反射到该实例的所有引用,还strs[0],strs[1]等等.发生这种情况是因为a List<T>引用类型.使用一个引用执行任何操作都将反映在所有引用中.另一方面,值类型将在将对象传递给方法时复制整个对象.因此,以下代码将在调用后i获得该值.4DoSomething

int i = 4;
var result = DoSomething(i);

void DoSomething(int j)
{
    j = -7;
}
Run Code Online (Sandbox Code Playgroud)

为了避免这种情况,你必须创建一个全新的列表,而不是仅仅添加现有的列表:

foreach (DataGridViewRow sr in dataGridView1.SelectedRows)
{
    if(i >= 10)
    {
        strs.Add(new List<string>(str));
        str.Clear();
        i = 0;
        var a = strs; //Here strs have one str with 0 values
    }
    str.Add(sr.Cells["MOBILNI"].Value.ToString().Trim());
    i++;
}
strs.Add(str);
Run Code Online (Sandbox Code Playgroud)