0

I know there are very similar questions but I need to know what's going on in this specific case. I wrote a function to reverse items of a multidimensional array along a specific dimension. To do this I convert the multidimensional array to a jagged array and than recursively find the array dimension where perform the reversal.

public static void Reverse(this Array array, int dimension, int start, int end)
{
    object[] jag = array.ToJaggedArray();

    if (!jag.ReverseAux(0, dimension, start, end))
        throw new ArgumentOutOfRangeException("dimension", dimension, "Dimension must be nonnegative and less than array dimensions number.");

    array = jag;
}

Now my problem is that when I run this method my input array has not been modified. Shouldn't an array be passed by reference? When I assign array = jag why it is correctly assigned inside the method but not outside?

For example:

// create 2D array of strings
string[,] ar = {{"00", "01", "02"},
                {"10", "11", "12"},
                {"20", "21", "22"}};
// reverse the first dimension (rows)
ar.Reverse(0, 0, 2);
// show the result
MessageBox.Show(ar.ToString(null, null));

The output is {{00, 01, 02}, {10, 11, 12}, {20, 21, 22}} that is exactly the original array. If I check the output in Reverse method

public static void Reverse(this Array array, int dimension, int start, int end)
{
    //...

    array = jag;
    System.Windows.Forms.MessageBox.Show(array.ToString(null, null));
}

this shows the correct reversed array {{20, 21, 22}, {10, 11, 12}, {00, 01, 02}}.

Shouldn't an array be passed by reference? Why after the local assignment my input array is referencing the orignal pointer and not the assigned? Should I use ref keyword for array argument? If yes is it possible to continue using this method as an extension of Array type?

PrinceOfBorgo
  • 508
  • 5
  • 14
  • Parameters are passed by value unless you use the `ref` or `out` modifiers. Extension methods don't support passing by reference however. – Lee Feb 05 '19 at 12:27
  • @Lee - There is also `in` modiier to pass by reference added in 7.3 – Shoter Feb 05 '19 at 12:29
  • @Shoter that won't help here neither. – Fildor Feb 05 '19 at 12:31
  • The confusion here is because C# hides pointers from the users, unless you explicitly tell so, every param is passed by value. An array is a continuous amount of memory, the parameter that you receive is actually the pointer to where that memory starts. Updates to the array items (array[x]) are reflected to the user, but the updates to the pointer (array variable itself) are not. – Juan Feb 05 '19 at 12:38
  • Possible duplicate of [Are arrays or lists passed by default by reference in c#?](https://stackoverflow.com/questions/967402/are-arrays-or-lists-passed-by-default-by-reference-in-c) – mjwills Feb 05 '19 at 12:57

1 Answers1

3

All references/values in paramaters of function other than with out and ref modifiers can be considered as solely local variables (though, you still can change values inside referenced objects).

In C# we do such extension methods like this, so it looks like it is stateless extension method:

public static Array Reverse(this Array array, int dimension, int start, int end)
{
    object[] jag = array.ToJaggedArray();

    if (!jag.ReverseAux(0, dimension, start, end))
        throw new ArgumentOutOfRangeException("dimension", dimension, "Dimension must be nonnegative and less than array dimensions number.");

    return jag;
}

var output = input.Reverse(...);
eocron
  • 6,885
  • 1
  • 21
  • 50