Re: Pass by reference vs Pass by Value (is 'data aliasing' a problem in C#?)

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



On Aug 1, 9:46 am, "Nicholas Paldino [.NET/C# MVP]"
<m...@xxxxxxxxxxxxxxxxxxxxxxxxxxx> wrote:


You would pass a reference type with a ref keyword or out keyword when
you need to modify what reference itself, not what the reference points to.
So if you have a StringBuilder parameter, and you want to point it to a
completely different StringBuilder instance, you have to use ref or out in
order to be able to change the reference.

I see what you mean. Microsoft has a great example (see Examples 4
and 5) on this point:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vclrfPassingMethodParameters.asp
I reproduce below for future reference.

However, I think that, using new(), you can actually do anything that
keyword ref is able to do, using passing-ref-by-value, rather than
using keyword 'ref' and passing-ref-by-reference, if you put a little
thought behind it. Agreed? (This is complete almost off-topic, since
I acknowledge your point). For example, if you change the reference
outside the method, then of course you can do whatever using keyword
'ref' and passing-by-reference would do inside the method. But that's
offtopic, since it's like saying you don't need to use a method to
achieve the same thing as using the method, which of course is almost
always true.


When you pass a reference type to a method, you can always modify what
the reference points to. The ref/out (or lack of it) is in reference (no
pun intended) to the reference itself, not what it points to.

Yes. But this is usually rare, hence no need to "pass-a-reference-by-
reference" (usually), just "pass-a-reference-by-value", since what the
reference points to is much more important (usually) than the
reference itself. That's why C# code seems to always omit the 'ref'
keyword--usually it's not important.


The reply from C# Corner by a poster, call him Brian, as to why 'ref'
is needed was to write out a simple demonstration program (see below),
which indeed seems to refute the above, and point out that unless you
use keyword "ref" in your method parameter, then you cannot change an
object passed to a method while inside the method.

Brian's example is wrong. While a parameter that is not passed by ref
can be modified in the method it is declared it, that change will not be
seen outside of the method. Brian is assigning a NEW instance of MyObject
to X in PassObjectByValue2 and then changing AMember to 2. This doesn't
change what was originally passed to PassObjectByValue2, because that is not
the object that the property was changed on.

Yes, though Brian's example was not so bad. Examples 4 and 5 below
from Microsoft make the point that I believe is being made here.


However--and this is the point of this post--it seems I've found a
workaround so that even with the use of "pass by value", you can
indeed change an object passed, inside the called method (when you
exit the method), if you use the assignment operator "=" and return a
new object (see below, at the comments ////). I don't think what's
known in C++ as 'aliasing' is an issue here when doing this
"workaround" (correct me if I'm wrong). That's really the point of
this post--can you have 'data aliasing' when you pass-by-value in C#,
since we're always dealing with references, and in theory it's
supposed to be safe? Is there any other potential problem to my
'workaround' below, as a coding style?

I don't see why you need a workaround here. Basically what it comes
down to is this. You will always be able to change members of a reference
type, whether or not it is passed by ref/out, or neither. If you want to
change what the reference actually points to, and have it be visibile
outside of the method, then you need ref/out.

Yes, that's right.

Fran

--
Thank you. I think I understand this topic now, based on the
Microsoft example below, part of which I reproduce below (the best
parts). I now understand what you mean by saying 'passing Reference
types by reference is rarely done' (or needs to be done), since, if
you look at Example 5 below (and compare it to Example 4), you'll see
that if you pass (a reference) by reference rather than (pass a
reference) by value, and you change the reference, you can easily
"orphan" your original data structure "pointed to" by the (now
changed) reference. I suppose the C# garbage collector will clean up
the "orphaned" data, and it won't be a memory leak (please confirm
this if you care too), but it seems that indeed doing something like
Example 5 below is "rare" or "rarely needs to be done" in an
'ordinary' program (please confirm). Fran


http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vclrfPassingMethodParameters.asp


Example 4: Passing Reference Types by Value


The following example demonstrates passing a reference-type parameter,
myArray, by value, to a method, Change. Because the parameter is a
reference to myArray, it is possible to change the values of the array
elements. However, the attempt to reassign the parameter to a
different memory location only works inside the method and does not
affect the original variable, myArray.

// PassingParams4.cs

// Passing an array to a method without the ref keyword.

// Compare the results to those of Example 5.

using System;

class PassingRefByVal

{

static void Change(int[] arr)

{

arr[0]=888; // This change affects the original element.

arr = new int[5] {-3, -1, -2, -3, -4}; // This change is
local.

Console.WriteLine("Inside the method, the first element is:
{0}", arr[0]);

}



public static void Main()

{

int[] myArray = {1,4,5};

Console.WriteLine("Inside Main, before calling the method, the
first element is: {0}", myArray [0]);

Change(myArray);

Console.WriteLine("Inside Main, after calling the method, the
first element is: {0}", myArray [0]);

}

}

Output

Inside Main, before calling the method, the first element is: 1

Inside the method, the first element is: -3

Inside Main, after calling the method, the first element is: 888

Code Discussion


In the preceding example, the array, myArray, which is a reference
type, is passed to the method without the ref parameter. In such a
case, a copy of the reference, which points to myArray, is passed to
the method. The output shows that it is possible for the method to
change the contents of an array element (from 1 to 888). However,
allocating a new portion of memory by using the new operator inside
the Change method makes the variable arr reference a new array. Thus,
any changes after that will not affect the original array, myArray,
which is created inside Main. In fact, two arrays are created in this
example, one inside Main and one inside the Change method.


Example 5: Passing Reference Types by Reference


This example is the same as Example 4, except for using the ref
keyword in the method header and call. Any changes that take place in
the method will affect the original variables in the calling program.

// PassingParams5.cs

// Passing an array to a method with the ref keyword.

// Compare the results to those of Example 4.

using System;

class PassingRefByRef

{

static void Change(ref int[] arr)

{

// Both of the following changes will affect the original
variables:

arr[0]=888;

arr = new int[5] {-3, -1, -2, -3, -4};

Console.WriteLine("Inside the method, the first element is:
{0}", arr[0]);

}



public static void Main()

{

int[] myArray = {1,4,5};

Console.WriteLine("Inside Main, before calling the method, the
first element is: {0}", myArray [0]);

Change(ref myArray);

Console.WriteLine("Inside Main, after calling the method, the
first element is: {0}", myArray [0]);

}

}

Output

Inside Main, before calling the method, the first element is: 1

Inside the method, the first element is: -3

Inside Main, after calling the method, the first element is: -3

Code Discussion

All of the changes that take place inside the method affect the
original array in Main. In fact, the original array is reallocated
using the new operator. Thus, after calling the Change method, any
reference to myArray points to the five-element array [not the three-
element array], which is created in the Change method.

.



Relevant Pages

  • Re: How can I pass a multidimensional array as a ref parameter in func
    ... static int ReadFile(ref ushortnArray, ... > Array variable is the pointer to the address. ... > No 'ref' is needed. ... Ref is needed if your variable is not a reference ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: slicing array references
    ... I'm working on some classes with attributes that are array and hash ... 0,1,2 in scalar context is 2. ... there is no need to try variations on how the ref got there. ... similarly, when you just want a single item from an aggregate reference, always use the -> notation. ...
    (perl.beginners)
  • Re: textbook authors: passing by ref is NOT more efficient!
    ... efficiency in terms of performance and we are talking reference objects. ... classic example (using int values, ... Console.WriteLine("Value after by ref routine ", ... reference to the array object even if you don't say "ref", ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Passing Objects by ref keyword as a convention
    ... practice all objects should be passed by reference using the ref ... keyword generally speaking because as the writer of code you are ... conveying your intentions that an Object should/can be modified by your ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: textbook authors: passing by ref is NOT more efficient!
    ... Ask them how long it takes to write a screen compared to the time difference in using 'ref' or not. ... reference to the array object even if you don't say "ref", ...
    (microsoft.public.dotnet.languages.csharp)