值类型与引用类型变量行为差异:为何数组赋值修改会影响原变量?
我仍在努力理解编程基础概念,此前一直忽略这个问题,但现在需要彻底掌握。请查看以下C#代码:
int m = 2; int n = m; n = 3; Console.WriteLine("n = "+n); Console.WriteLine("m = "+m); Console.WriteLine(); int[] x = {1}; int[] y = x; y[0] +=1; Console.WriteLine("x[0] = "+ x[0]); Console.WriteLine("y[0] = "+ y[0]); Console.WriteLine(); Console.WriteLine(x==y); Console.WriteLine(n == m);
输出结果:
n = 3 m = 2 x[0] = 2 y[0] = 2 True False
当值类型变量n赋值为m后,修改n的值不会改变m的值;但数组执行y=x后修改y[0],x[0]也会随之改变。我知道用ToArray方法可创建新副本避免影响原数组,想了解值类型变量与数组(引用类型)的行为差异原因。
核心差异解释
C#变量分为值类型和引用类型,二者赋值时的行为本质区别在于传递的内容不同:
值类型的赋值逻辑
值类型(比如int、bool、自定义struct等)直接存储实际的数据值。执行int n = m时,是把m内存中的数值(2)完整复制一份到n的独立内存空间里。此时m和n完全独立,修改任意一个变量的值,都只会改变自身内存区域的内容,不会影响另一个变量,所以最终m还是2,n变为3,n == m返回False。引用类型的赋值逻辑
数组属于引用类型,引用类型的变量并不存储实际数据,而是存储指向数据所在内存地址的引用(可以理解为指向数据的“指针”)。执行int[] y = x时,并没有复制数组的元素,只是把x存储的内存地址复制给了y。此时x和y指向同一块内存中的同一个数组对象,修改y[0]本质是修改共享内存里的数组元素,x读取同一位置时自然会看到变化。而x == y返回True,是因为两个变量存储的引用地址完全相同,指向同一个对象。如何避免引用类型的共享修改
如果想让数组赋值后互不影响,需要创建原数组的独立副本,比如使用ToArray()方法,它会生成一个新的数组对象,并将原数组的元素复制到新数组中。此时新数组和原数组位于不同的内存区域,修改其中一个不会影响另一个。
内容的提问来源于stack exchange,提问作者Yugraaj Sandhu

