Why would ref be used for array parameters in C#?
Asked Answered
I

2

8

I read the page Passing Arrays Using ref and out (C# Programming Guide) and was wondering why we would need to define an array parameter as a ref parameter when it is already a reference type. Won't changes in the callee function be reflected in the caller function?

Illumination answered 8/10, 2013 at 19:54 Comment(2)
Yes they will, which is the reason for using ref.Quasi
Since the changes will be reflected, isnt that enough rather than using ref explicitlyIllumination
A
32

Won't changes in the callee function be reflected in the caller function?

Changes to the contents of the array would be reflected in the caller method - but changes to the parameter itself wouldn't be. So for example:

public void Foo(int[] x)
{
    // The effect of this line is visible to the caller
    x[0] = 10;

    // This line is pointless
    x = new int[] { 20 };
}
...
int[] original = new int[10];
Foo(original);
Console.WriteLine(original[0]); // Prints 10

Now if we changed Foo to have a signature of:

public void Foo(ref int[] x)

and changed the calling code to:

Foo(ref original);

then it would print 20.

It's very important to understand the difference between a variable and the object that its value refers to - and likewise between modifying an object and modifying a variable.

See my article on parameter passing in C# for more information.

Applause answered 8/10, 2013 at 19:58 Comment(5)
To elaborate... with arrays you can't traditionally modify the size without creating an entirely new array. So you might want to use the ref or out keywords when you want to replace it with a new array to effectively change the size.Nazarite
@TrevorElliott: Except of course it wouldn't really "replace the array" - it would change the value of a single variable which referred to the array and which was used as the argument. Any other variables which referred to the original array would still refer to the original array.Applause
True, which is why this is generally a bad idea and why using a List<T> is a much better option if you need a dynamically sized collection.Nazarite
And the BCL does offer this resize philosophy: Array.Resize(ref x, 10); changes x which could be an int[] for example into a new instance of length 10; see Resize.Febrifugal
The problem with Array.Resize is it's very expensive in terms of processing times compared to a list.Illumination
N
5

If you only plan to change the contents of the array, then you're correct. However, if you plan on changing the array itself, then you must pass by reference.

For example:

void foo(int[] array)
{
  array[0] = 5;
}

void bar(int[] array)
{
  array = new int[5];
  array[0] = 6;
}

void barWithRef(ref int[] array)
{
  array = new int[6];
  array[0] = 6;
}


void Main()
{
  int[] array = int[5];
  array[0] = 1;

  // First, lets call the foo() function.
  // This does exactly as you would expect... it will
  // change the first element to 5.
  foo(array);

  Console.WriteLine(array[0]); // yields 5

  // Now lets call the bar() function.
  // This will change the array in bar(), but not here.
  bar(array);

  Console.WriteLine(array[0]); // yields 1.  The array we have here was never changed.

  // Finally, lets use the ref keyword.
  barWithRef(ref array);

  Console.WriteLine(array[0]); // yields 5.  And the array's length is now 6.
}
Nonjoinder answered 8/10, 2013 at 20:0 Comment(2)
"Jon beat me to the right answer. Darn! I am Jack's broken Heart."Illumination
I know it's been a long time but this answer has confused me. When you call bar() it should return 5 (not 1), right? Because you have modified the array through foo()Prohibitory

© 2022 - 2024 — McMap. All rights reserved.