为什么一个数组在没有引用的情况下传递,在方法内部被 CopyTo 更改?

Why is an array passed without ref, changed by CopyTo inside the method?

由于传入的数组参数没有ref关键字,这段代码输出数组的初始值(即1...6):

using System;
using System.Linq;

class Program 
{
    static void Main(string[] args) 
    {
        var arr = new int[] {1, 2, 3, 4, 5, 6};

        Rotate(arr, 3);
        
        Console.WriteLine(string.Join(',', arr));
    }

    static void Rotate(int[] nums, int k)
    {
        var tail = nums.TakeLast(k).ToArray();
        nums = tail.Concat(nums)
            .Take(nums.Length)
            .ToArray();
    }
}

很明显,因为在 Rotate 方法内部有它自己的数组,其中包含从参数值复制而来的值。如果我想在调用方法中更改 arr 值,我需要通过 ref 将它传递给 Rotate 方法,它可以工作。 但我不明白,为什么如果用 CopyTo() 方法替换赋值,参数的行为就像它通过引用传递一样:

static void Rotate(int[] nums, int k)
{
    var tail = nums.TakeLast(k).ToArray();

    tail.Concat(nums)
        .Take(nums.Length)
        .ToArray()
        .CopyTo(nums, 0);
}

因为CopyTo()将元素设置在数组内部,并不会重新分配数组变量本身。

.ToArray() 创建一个新对象,而 CopyTo() 修改它。后者通过对现有数组的引用。

另见 Passing Arrays by Value and by Reference 和许多其他内容。

下面将以图形方式解释发生的情况。您的 3 种方法(常规、CopyTo 和 ref)非常不同..

我已经概述了交换算法的相对复杂性,但大多数情况下您可以忽略它。所有这一切最重要的一点是当您使用 ref 时会发生什么,以及当您操作正在传递的引用类型的 contents 时会发生什么。内容操作与将整个内容换成其他内容非常不同

点击展开..