Reputation: 198
I do not understand why this function was written like that:
System.Array.Resize<int>(ref int[], int)
If arrays are passed by reference by default why wasn't it written like that:
System.Array.Resize<int>(int[], int)
Upvotes: 3
Views: 562
Reputation: 471
Simply speaking if your array is passed to a method as a ref
parameter it can be replaced as a whole with another array created within the method.
It's not the case with arrays passed without ref
keyword.
Code below illustrates the difference.
Note that individual elements of array parameters can be replaced in both cases (with of without ref
keyword).
class Program
{
static void PrintArr(string comment, int[] arr)
{
Console.WriteLine($"{comment}:");
Console.WriteLine(string.Join(", ", arr.Select(e => e.ToString())));
}
static void NoRef(int[] arr)
{
int[] localArr = { 2, 4, 8, 10 };
arr = localArr;
}
static void ByRef(ref int[] arr)
{
int[] localArr = { 2, 4, 8, 10 };
arr = localArr;
}
static void Main()
{
int[] arr;
arr = new int[] { 1, 3, 4, 7, 9 };
PrintArr("Before NoRef is called", arr);
NoRef(arr);
PrintArr("After NoRef is called", arr);
PrintArr("Before ByRef is called", arr);
ByRef(ref arr);
PrintArr("After ByRef is called", arr);
Console.ReadLine();
}
}
}
Output for the code is shown below (note that ByRef method code replaced the array.
Before NoRef is called:
1, 3, 4, 7, 9
After NoRef is called:
1, 3, 4, 7, 9
Before ByRef is called:
1, 3, 4, 7, 9
After ByRef is called:
2, 4, 8, 10
Upvotes: 1
Reputation: 5506
This is because when we write a variable to a reference type object, there are kind of 2 parts, the actual object instance, and the reference which the variable name represents (32bit or 64bit memory address pointer internally, platform dependant). You can see that clearly with this sharplab.io snippet.
When we call a method, this pointer is copied, but the instance isn't, so:
var a = new Blah {Prop = "1"}; // Blah is a class, a reference type
Method(a);
void Method(Blah blah)
{
blah.Prop = "2"; // changes the shared instance, we know this.
blah = new Blah {Prop = "3"}; // has no effect.
}
Console.WriteLine(a.Prop); // 2
You see when we set blah
inside of the method, we are mutating our local reference, not the shared one. Now if we use the ref
keyword:
var a = new Blah {Prop = "1"};
Method(ref a);
void Method(ref Blah blah)
{
blah.Prop = "2"; // changes the shared instance, we know this.
blah = new Blah {Prop = "3"}; // now changes ref a outside
}
Console.WriteLine(a.Prop); // 3!
because the parameter blah
is passed by reference, when we mutate it, we mutate the original reference a
.
Upvotes: 6
Reputation: 273380
Arrays are indeed reference types, which means that changes done to the passed-in array object inside a method will be reflected on the caller's side:
public static void Foo(int[] a) {
a[0] = 1;
}
// ...
int[] a = new int[1];
Foo(a);
Console.WriteLine(a[0]); // 1
However, if you set the array to something else inside the method:
public static void Foo(int[] a) {
a = null;
}
// ...
int[] a = new int[1];
Foo(a);
Console.WriteLine(a[0]); // will not throw NRE
Declaring the parameter as ref
will allow reassignments to the parameter to reflect on the caller's side.
Changing the size of the array requires creating a new array and hence re-assigning the parameter. You can't resize an array by mutating an existing array object somehow. This is why it needs to be declared as ref
.
Upvotes: 3