c#:全局变量值已更改,即使它没有在循环中分配新值

c#: Global variable value changed even though it doesn't be assigned new value in a loop

谁能帮忙解释一下为什么会得到这个结果?我期望的结果是“1,2”。

        var list1 = new List<int> { 1, 2 };
        List<List<int>> listStrs = new List<List<int>> { new List<int>{100,101 }, new List<int>{ 200, 201 } };
        foreach (var listStr in listStrs)
        {
            List<int> list2 = list1; //the way try to get expected result: List<int> list2 = list1.Select(i => i).ToList();
            list2.AddRange(listStr);
        }
        Console.WriteLine(String.Join(",",list1));

//结果return: 1,2,100,101,200,201

List<T> 引用类型 。当您执行以下操作时:

 List<int> list2 = list1;

你实际上在做的是告诉编译器复制变量 list1 的值并将其分配给 list2。您必须了解变量只是 的占位符。在引用类型中,变量的 value 是对象“所在”的“内存地址”。因此,list2list1 都“指向”(或引用)完全相同的对象;有两个变量,但只有一个列表。

这很明显,只需做:object.ReferenceEquals(list1, list2)。它将 return true.

List<int> list2 = list1.Select(i => i).ToList(); 如您所愿,因为投影 (Select) 创建了一个 new 列表。这个新列表和 list1 是完全不同的实例,每个都“生活”在不同的内存位置并且完全无关; object.ReferenceEquals(list1, list2) 将 return false.

现在,请记住,事情随着值类型而改变。值类型变量中“存储”的值是实例本身;没有涉及值类型的引用(除非它们被装箱)。

因此,代码如下:

struct EvilMutableStruct
{
    public int i
}

var e1 = new EvilMutableStruct();
var e2 = e1;
e2.i = 1;
Console.WriteLine(e1.i == 1); //prints false!

为什么?因为,e2 = e1 的意思是一样的;复制存储在 e1 中的值并将其分配给 e2。因为 e1 的值是值类型实例本身,所以会制作对象的副本并将其存储在 e2 中。现在两个值类型变量都包含两个相同但 不同 值类型实例。