阵列的第二个元素发生了什么?

时间:2017-03-17 13:41:10

标签: c#

假设我写了

int numbers[] = {1,2,3};
ref int second = ref numbers[1];
Array.Resize(ref numbers, 1);
Console.WriteLine(second); // works fine
second = 321; // also legit

这是如何工作的?我是否在托管堆上神奇地将numbers[1]分配为单独的可寻址号码?这里发生了什么?

2 个答案:

答案 0 :(得分:9)

Array.Resize根据the documentation创建一个新数组,将旧数组保留在堆上:

  

此方法使用指定大小将元素从旧数组分配到新数组,然后用新数组替换旧数组。

(我的重点)

注意:根据您的理解,文档会略有误导。它说“然后用新的阵列取代旧阵列”。这意味着它取代了您在示例中的数组变量numbers中的引用,并引用了新数组。旧数组对象保持不变并且在内存中不受影响。

如果你没有ref int引用它,那么GC最终会把它拿起来,但是既然如此,那就不会。

second = 321更改了原始数组,而不是新数组。

您可以使用一个非常简单的示例轻松展示:

using System;

public class Program
{
    public static void Main()
    {
        int[] a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        int[] b = a;
        ref int a1 = ref a[1];

        Array.Resize(ref a, 5);

        a1 = 100;
        Console.WriteLine(a[1]); // new
        Console.WriteLine(b[1]); // original
        Console.WriteLine(ReferenceEquals(a, b));
    }
}

输出:

2            // the new array, which did not change
100          // the original array, which did change
false        // not the same arrays

所以ref int变量确实发生了变化,原始数组发生了更改,但新的,经过尺寸修改的副本却没有。

See this example on .NET fiddle

答案 1 :(得分:3)

  

此方法分配具有指定大小的新数组,将旧数组中的元素复制到新数组,然后用新数组替换旧数组.array必须是一维数组。

     

如果array为null,则此方法创建一个具有指定大小的新数组。

     

如果newSize大于旧数组的长度,则分配一个新数组,并将所有元素从旧数组复制到新数组。如果newSize小于旧数组的长度,则分配一个新数组,并将元素从旧数组复制到新数组,直到填充新数组为止。旧数组中的其余元素将被忽略。如果newSize等于旧数组的Length,则此方法不执行任何操作。

直接来自MSDN