0

As the array parameter is passed without ref-keyword, this code outputs initial value of array (i.e. 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();
    }
}

It is obvious, because inside the Rotate method there is it's own array with values, copied from the parameter values. And if I want to change arr values in the calling method, I need to pass it to the Rotate method by ref, it works. But I don't understand, why if replace assignment with CopyTo() method the parameter behaves as like it is passed by reference:

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

    tail.Concat(nums)
        .Take(nums.Length)
        .ToArray()
        .CopyTo(nums, 0);
}
TheMaster
  • 45,448
  • 6
  • 62
  • 85
bryukva
  • 3
  • 2
  • Arrays are *reference types* therefore when you pass one to a method, a copy of a *reference* to the array is passed (the reference itself is passed by value). Therefore the array `nums` inside the method has the same reference as the one passed to the method. They are the same array. – Matthew Watson Oct 07 '21 at 09:20
  • I see, but why the first example of code outputs 1...6 then? And if I add `Console.WriteLine(string.Join(',', nums));` in the end of Rotate, it will print '4,5,6,1,2,3'? Moreover, why adding ref also leads to '4,5,6,1,2,3' output? – bryukva Oct 07 '21 at 09:32
  • *is it's own array with values, copied from the parameter values* - but you do understand that the "copying" takes place at the point where ToArray is called, and not at the point the method is called? On the very first line of Rotate (the `{` conceptually), before even `TakeLast(k)` has executed, `nums` as an alternative variable reference to the same in-memory array that `arr` references. Shortly after this, `nums` is pointed to some new array somewhere else in memory (in the first code block) that is then promptly thrown away when the method ends – Caius Jard Oct 07 '21 at 09:41

2 Answers2

1

Here's a go at explaining what happens, graphically. Your 3 approaches (regular, CopyTo, and ref) are very different..

I've sketched in the relative complexity of the swapping algo but mostly you can ignore it. The most important point about all this is around what happens when you use ref, and what happens when you manipulate the contents of a reference type that is being passed around. Contents manipulation is very different to swapping the whole thing out for something else

Click to expand..

enter image description here

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
-1

Because CopyTo() sets the elements inside the array and does not reassign the array variable itself.

.ToArray() creates a new object while CopyTo() modifies it. The latter gets passed a reference to an existing array.

See also Passing Arrays by Value and by Reference and many others.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272