Using 'ref' when already reference variable

  • Thread starter Thread starter Doug
  • Start date Start date
D

Doug

Is there any harm in passing an object into a method with the 'ref'
keyword if the object is already a reference variable? If not, is
there any benefit?
 
Doug said:
Is there any harm in passing an object into a method with the 'ref'
keyword if the object is already a reference variable? If not, is
there any benefit?

That is the default for objects.
 
Using 'ref' for an object means that the method may change which object is
being pointed to. So, yes - there is some harm in using 'ref' when you don't
want to allow the method to change which object is being pointed to.

But you may not have a choice - if the method has a 'ref' param, you must
use the 'ref' keyword on the argument (in C#).
--
David Anton
www.tangiblesoftwaresolutions.com
Instant C#: VB.NET to C# Converter
Instant VB: C# to VB.NET Converter
Instant C++: C# to C++ Converter
Instant J#: VB.NET to J# Converter
 
Cool said:
Actually the default (for everything) is *by-value* passing. See
<http://www.yoda.arachsys.com/csharp/parameters.html>.

I guess (from your article) this is what I meant to say:

"This difference is absolutely crucial to understanding parameter
passing in C#, and is why I believe it is highly confusing to say that
objects are passed by reference by default instead of the correct
statement that object references are passed by value by default."
 
All of this has been very helpful, but has lead me to another question.
Say I have a method like so:

private bool TestMethod(myFirstClass oFirstClass, mySecondClass
oSecondClass, myThirdClass oThirdClass)
{
...code here
}

and I'm not concerned with whether or not they set the value of those
objects to null inside this method or not but do want them to have the
ability to modify properties of the three class within them (which they
can regardless if they pass the parameters with the 'ref' keyword or
not).

What I am concerned with is that I may call this method many, many
times under different threads. From what I understand of the reading I
did of the document you put in your response, that would mean that each
time this method is called a new instance of each class is created of
the variables since they are not passed with the 'ref' keyword. From a
memory point of view this would be bad wouldn't it?
 
Doug said:
private bool TestMethod(myFirstClass oFirstClass, mySecondClass
oSecondClass, myThirdClass oThirdClass)
{
...code here
}

[...]

From what I understand of the reading I
did of the document you put in your response, that would mean that each
time this method is called a new instance of each class is created of
the variables since they are not passed with the 'ref' keyword.

Your understanding is wrong. No new instances are created whether or not
'ref' is used.

Consider (MyClass is a class):

void Foo(MyClass myClass) {
...
}

When myClass is passed, it is passed by value. The value that is passed is
an /object reference/, since MyClass is a reference type. (An
/object reference/ is like a pointer to an object on the heap.)

Consider (MyClass is a class):

void Foo(ref MyClass myClass) {
...
}

When myClass is passed, it is passed by reference. The passed reference
**refers to** the /object reference/. (A reference to an /object reference/
is kind of like a pointer to a pointer.)

If this still isn't clear perhaps try reading the article I linked to
*again*, asking here about any parts you're unsure about.
 
Thanks. I figured out after I posted previously that I still didn't
get it. It's a pointer thing and I always get confused by that. But I
think I got it now. Thank you!
 
Cool said:
When myClass is passed, it is passed by reference. The passed reference
**refers to** the /object reference/. (A reference to an /object reference/
is kind of like a pointer to a pointer.)

Well, isn't it just more like a pointer to an object -- or value?

Another thing, they say it's an object reference passed by value to the
method.

Ok, so that means if the object(class instance) gets an update (member
changes) that when I use the handle to the object, it should reflect the
updated value. Right?

And can if you did use the 'ref' keyword, wouldn't it then pass an
object reference to an object by reference instead of by value?

That would mean that would be more like a pointer to a pointer. What
that means is that I could change the object that is being pointed to by
the first pointer and the second reference would automatically be
pointing to that 2nd object.
 
John A. Bailo said:
Well, isn't it just more like a pointer to an object -- or value?

That sounds more like the case where ref *isn't* used. In the part you
quoted I was referring to it being used.
Another thing, they say it's an object reference passed by value to the
method.

In the case of ref *not* being used, yeah.
Ok, so that means if the object(class instance) gets an update (member
changes) that when I use the handle to the object, it should reflect the
updated value. Right?

Yep. That's why the following works prints 'testing', not 'test':

using System;
using System.Text;

class Test {
static void Main() {
StringBuilder sb = new StringBuilder("test");
Append(sb);
Console.WriteLine(sb);
}

static void Append(StringBuilder sb) {
sb.Append("ing");
}
}
And can if you did use the 'ref' keyword, wouldn't it then pass an
object reference to an object by reference instead of by value?

An object reference would be passed to a method by reference instead of by
value.
That would mean that would be more like a pointer to a pointer. What
that means is that I could change the object that is being pointed to by
the first pointer and the second reference would automatically be
pointing to that 2nd object.

Indeed. This is how I tend to visualise it (with the arrows meaning 'refers
to'):

reference --> object reference --> object (on heap)

The object reference in the middle can be changed via the reference on the
left to refer to another object on the heap (or null).

For example, in the following 'False' is printed:

using System;
using System.Text;

class Test {
static void Main() {
StringBuilder sb = new StringBuilder("test");
StringBuilder original = sb;

PseudoAppend(ref sb);
Console.WriteLine(Object.ReferenceEquals(sb, original));
}

static void PseudoAppend(ref StringBuilder sb) {
// modify the original object reference to refer to
// a new object
sb = new StringBuilder("testing");
}
}

Had the StringBuilder been passed by value instead (i.e. had 'ref' not been
used) 'True' would've been printed as the object reference Main.sb would
not have been modifiable from within PseudoAppend.
 
This pretty much answers all cases /except/ how do you pass an object by
value...where it clones the object so I can make changes to it without
changing the original?
 
John A. Bailo said:
This pretty much answers all cases /except/ how do you pass an object by
value...where it clones the object so I can make changes to it without
changing the original?

You could make it a struct instead of a class. Then the *value* gets passed
by value instead of the *reference* getting passed by value.

Or you could make the class immutable - then no state can be changed
anyway.

Or you could manually clone the instance and then pass the reference to
this *cloned* instance instead of passing the reference to the *original*
instance.
 
Back
Top