user1049522
user1049522

Reputation: 11

passing array to function with or without ref keyword

I'm trying to do something with array passed to the function in .NET and I'm a little confused. Array is reference type so changes made to array passed to the function are visible outside the function. Example

static void Main(string[] args)
{
    byte[] arr = new byte[] { 1,2, 3, 4, 5 };    
    Console.WriteLine(string.Join("", arr));        //console output: 12345
    doSomething(arr);
    Console.WriteLine(string.Join("", arr));        //console output: 52341
}
static void doSomething(byte[] array)
{
    byte tmp = array[0];
    array[0] = array[array.Length - 1];
    array[array.Length - 1] = tmp;
}

so it works exactly the same as with "ref" keyword used (same console output)

doSomething(ref arr);  for static void doSomething(ref byte[] array)

However if I add following line to my function:

array = (new byte[] { 1 }).Concat(array).ToArray(); //size of array is changed

the results are different:

12345
52341// "ref" keyword is not used

and

12345
152341 "ref" keyword is used

Could someone explain me why results are different ?

Upvotes: 0

Views: 336

Answers (2)

Nick Bray
Nick Bray

Reputation: 1963

value type variables are variables containing a value. arr is object variable that points to an instance of byte[] in memory. When you pass it by value to the method doSomething you are passing a pointer to the instance of byte[] in memory. This way both arr and array both point to the same instance of byte[] in memory. If DoSomething changes the instance of byte[] that both arr and array are pointing too it does not actually change the variable arr, since it is still pointing to the same place in memory. However, since arr is still pointing to the same place in memory and the instance in that place has been updated, then arr can "see" the changes.

When you call Concat it generates a new instance of byte[] somewhere else in memory, and it poitns the variable array to the new instance in memory. The old instance of byte[] still exists, and arr is still pointing to it.

When you pass the variable arr by ref, then any change to where array is pointing will also affect where arr is pointing. When it is not passed by ref DoSomething can only change the instance of byte[] in memory that arr points to, but it cannot change where arr is pointing.

That is why there is a difference between passing an object by reference and passing an object by value.

Upvotes: 2

sll
sll

Reputation: 62544

For any parameter passed in a method without Ref keyword - local variable created and represents a copy of original parameter value. So when you passed in reference type variable arr - this is really Int32 reference which points to some address let's say ADDR. Then in a method copy of this variable is created whcih completely unbound from original paremeter (arr). But still points to the same address in a memory and you still can change underlying original data. And when you change reference value itself by assigning = new ... local copy of reference value is changed but this change does not affect original reference passed in a method.

If you want to "bind" original reference and a new one created in a method by new() - use Ref, by specifying Ref you are saying "I want to pass a reference by/to reference".

After following line:

array = (new byte[] { 1 }).Concat(array).ToArray();
  • In case of Refparameter: reference changed but since it is passed by reference (Ref) - original reference affected as well
  • In case of default parameter passing: local copy of reference is changed but original is not affected so you got a new reference which points to a newly created array

Upvotes: 0

Related Questions