ref parameter

R

Raj

1. What actually happens when a parameter to a method is passed by ref?
2. And, whether the same thing happens while we pass a parameter by out?
3. Whether boxing/unboxing happens while we pass parameter by ref and get
the value?

Thank you

Regards
Raj
 
P

Peter Duniho

Raj said:
1. What actually happens when a parameter to a method is passed by ref?

That's a very open-ended question.

From the language perspective, whatever variable is used as the
argument is essentially aliased by the argument. That is, changes to
the argument in the method will be reflected in the variable passed as
the argument.

Technically, the argument is passed "by reference". That is, rather
than the value of the argument being passed as the argument (i.e. passed
"by value"), a reference to the argument itself is passed and all uses
of the argument in the method go through that reference.

That's the high-level description of what "ref" does. Of course, if you
are interested in the exact rules and precise way "ref" and "out" are
defined according to the C# specification, you can always consult the
specification.

As far as the exact implementation details go, that can be observed,
whether you are interested in the MSIL or in the compiled native code.
But of course these are just implementation details.
2. And, whether the same thing happens while we pass a parameter by out?

Yes. In fact, if I recall correctly, the MSIL doesn't distinguish
between "ref" and "out". Just "pass by value" versus "pass by reference".
3. Whether boxing/unboxing happens while we pass parameter by ref and get
the value?

No. Boxing happens when a value of a value type is used in a context
where the expression is of type System.Object, a reference type. It has
nothing to do with passing by reference.

Pete
 
P

Peter Duniho

Peter said:
Raj said:
1. What actually happens when a parameter to a method is passed by ref?

That's a very open-ended question.

From the language perspective, whatever variable is used as the
argument is essentially aliased by the argument. That is, changes to
the argument in the method will be reflected in the variable passed as
the argument.

Technically, the argument is passed "by reference". That is, rather
than the value of the argument being passed as the argument (i.e. passed
"by value"), a reference to the argument itself is passed and all uses
of the argument in the method go through that reference. [...]

Re-reading that, the above may be a bit confusing, because I've used the
word "argument" to mean two different things. Perhaps this wording is
more clear:


Technically, the argument is passed "by reference". That is,
rather than the value of the variable being passed as the
argument (i.e. passed "by value"), a reference to the variable
itself is passed and all uses of the argument in the method
go through that reference.

Note that implied in this description is that to pass "by reference",
you must be passing a variable. That is, something for which you can
actually take a reference and modify through that reference.

Pete
 
C

Christoph Basedau

Raj said:
1. What actually happens when a parameter to a method is passed by ref?

it's passed by ref ;-)

this means if you modify its value inside the function, it'll stay
modified after having returned.
In- and outside the function you work on the same data/address,
whilst you work on a copy inside the function, if it's passed by value.

Ref-types are btw always passed by ref - no explicit ref keyword needed.
2. And, whether the same thing happens while we pass a parameter by out?

Basically yes.
'out' iirc is a C#-special. It resolves to 'ref' on the CLR-level.
A param passed as 'out' is guaranteed to be assigned inside the
function, so the callers do not need to initialze/assign it.

So:

int i;
int.TryParse ("20", out i);

is syntactically correct.
If TryParse had a ref-param, the i-variable
would have to get initialized first.
3. Whether boxing/unboxing happens while we pass parameter by ref and get
the value?

Boxing occurs when you put a value type into an object-wrapper.
It is not necessarily/directly associated with the the
issue of ref/out passing-conventions.

Christoph
 
D

David Anton

Reference types are *not* always passed by ref - you need to use the 'ref'
keyword for that. It's the same as in Java if you leave out the 'ref' - you
can modify the internals of the object, but not the top-level reference.
e.g., if you want the argument to refer to a new object after the method is
called, you must use 'ref'. If you just need to modify an existing reference
instance, then you don't need 'ref'.
 
C

Christoph Basedau

David said:
Reference types are *not* always passed by ref - you need to use the 'ref'
keyword for that. It's the same as in Java if you leave out the 'ref' - you
can modify the internals of the object, but not the top-level reference.
e.g., if you want the argument to refer to a new object after the method is
called, you must use 'ref'. If you just need to modify an existing reference
instance, then you don't need 'ref'.

Good point. An actually true.
But to my defense, the two are both colloquially referred
to as 'by ref'.
And it's a matter of definition whether "by reference"
implicates, that you not only get a reference to an object
(or other reftype) passed into a function - and not a copy -
but that you are able to make the reference refer
to something else - also on return.

The Name "Reference type" at least was chosen, because
instances of thess types, are passed by ref (in the restricted sense)
where as "Values types" are passed as (shallow) copies, which
makes one of the major difference between classes
and structs, for example.


Christoph
 
P

Peter Duniho

Christoph said:
Good point. An actually true.
But to my defense, the two are both colloquially referred
to as 'by ref'.

No, not really. Only by those who conflate the two incorrectly are they
both referred to as "by ref".
And it's a matter of definition whether "by reference"
implicates, that you not only get a reference to an object
(or other reftype) passed into a function - and not a copy -
but that you are able to make the reference refer
to something else - also on return.

It's a matter of definition, but the definition is specific and
well-known, and matches what David is describing.
The Name "Reference type" at least was chosen, because
instances of thess types, are passed by ref (in the restricted sense)

No, that's not why the name "reference type" was chosen. The name was
chosen because variables of that type always are a reference to an
instance of the object, rather than storing the value in the variable
itself.

The name choice has nothing to do with passing by reference.
where as "Values types" are passed as (shallow) copies, which
makes one of the major difference between classes
and structs, for example.

Both reference types and value types are passed by value by default. A
reference type variable is a reference, so the value passed is a
reference. But it's still passed by value.

See http://www.yoda.arachsys.com/csharp/parameters.html for more details.

Pete
 
B

Ben Voigt [C++ MVP]

3. Whether boxing/unboxing happens while we pass parameter by ref and get
No. Boxing happens when a value of a value type is used in a context
where the expression is of type System.Object, a reference type. It has
nothing to do with passing by reference.

True that passing by ref parameter doesn't cause boxing. But "get the
value"? There could and will be boxing involved if there would be boxing
accessing the caller's variable.

e.g.

void func(ref int i)
{
System.WriteLine(i); // calls WriteLine(object) with boxing
}

or

void func2(ref object o)
{
if (o is int) { int a = (int)o + 3; } // unboxing
}


In both cases a ref parameter is boxed, but not because it is a ref
parameter. A normal pass-by-value parameter would have been boxed in the
same way.
 
P

Peter Duniho

Ben said:
[...]
In both cases a ref parameter is boxed, but not because it is a ref
parameter. A normal pass-by-value parameter would have been boxed in
the same way.

That's right. And because of that, exactly as I wrote, "it has nothing
to do with passing by reference".

There's nothing in my post that should be construed as suggesting that
passing by reference completely avoids boxing. I simply said, and
accurately so, that passing by reference and boxing don't have anything
to do with each other.

Pete
 
B

Ben Voigt [C++ MVP]

Peter Duniho said:
No, not really. Only by those who conflate the two incorrectly are they
both referred to as "by ref".

Sometimes it's helpful to use the word "handle" instead of reference when
talking about addressing instances of reference types, then there's no
confusion at all.
It's a matter of definition, but the definition is specific and
well-known, and matches what David is describing.


No, that's not why the name "reference type" was chosen. The name was
chosen because variables of that type always are a reference to an
instance of the object, rather than storing the value in the variable
itself.

The name choice has nothing to do with passing by reference.


Both reference types and value types are passed by value by default. A
reference type variable is a reference, so the value passed is a
reference. But it's still passed by value.

Types are never passed (as function parameters anyway, generics do receive
types). Instances of value types are passed as a copy by default, you can
use the "ref" keyword to pass a reference. Instances of reference types
cannot be stored in a variable (or a function parameter) at all, the
variable actually holds a handle to the instance and this handle is copied
by default, you can also pass the handle by reference which lets you replace
it with a handle to a different instance (or null).
 
C

Christoph Basedau

Peter said:
No, not really. Only by those who conflate the two incorrectly are they
both referred to as "by ref".

The conflation comes from the limitation of two keywords for
more then two possible ways of passing a "thing".

If you think of a complex data type, that is implemented as
a reference type, a "class" in C#, and you have a entity of
this type, an "instance", and you want to pass it to a function,
then you have at least three theoretic options of passing it.

a) pass a reference to the reftype-variable, e.g. use the
same storage location as the caller.
Needs ref/out-keyword in C#.
b) pass a copy of the reftype-variable, e.g. use different storage,
that yet refers ("points") to the same memory.
default behavior in C#.
c) pass a copy of the data
not possible in C#/.NET for ref-types, but possible in native C++,
for classes, and default for value types/structs in C#.

a) and b) concur functionally insofar, that you deal with the same
memory, the same "data". They differ, as the other gentleman said,
in the way a change of the reference, e.g. which chunk of memory is
referenced, is returned. It is returned for a)
but swallowed for b) for obvious reasons.
It's a matter of definition, but the definition is specific and
well-known, and matches what David is describing.

Yes, as I said, David was completely right.
I was also right, though my wording was kind of misleading.
No, that's not why the name "reference type" was chosen. The name was
chosen because variables of that type always are a reference to an
instance of the object, rather than storing the value in the variable
itself.
The name choice has nothing to do with passing by reference.

Of course the word "reference" has a similar meaning in both contexts.
Both reference types and value types are passed by value by default. A
reference type variable is a reference, so the value passed is a
reference. But it's still passed by value.

Which functionally makes a big difference, though it's formally the
same, because what you copy is completely different for the different
types.

Christoph
 
P

Peter Duniho

Ben said:
Sometimes it's helpful to use the word "handle" instead of reference
when talking about addressing instances of reference types, then there's
no confusion at all.

That depends entirely on how you've defined "handle" and how the person
to whom you're speaking defines "handle".

Traditionally, the word "handle" implies a double-dereference. For
example, a Windows handle for an allocation (you get the handle, then
you lock the handle to get the pointer), or in Mac OS prior to version
X, where the handle was in fact a pointer to a pointer (since the OS
used cooperative multitasking, you could safely avoid locking it for
simple accesses, just by dereferencing the handle...just don't do
anything that might interact with the memory manager while using the
dereferenced handle's pointer).

That's not at all what a reference type is in .NET. Using the word
"handle" would only confuse things if you are discussing it with someone
who is familiar with the older memory management models where the term
"handle" first arose.

In any case, the type is referred to as a "reference type". Suggesting
that one uses a "handle" instead of a "reference" to refer to an
instance of a "reference type" seems to me like it would only add an
extra layer of definitions, making it harder to understand. I mean, we
don't call it a "handle type", after all.
[...]
Both reference types and value types are passed by value by default.
A reference type variable is a reference, so the value passed is a
reference. But it's still passed by value.

Types are never passed (as function parameters anyway, generics do
receive types). [...]

It never occurred to me that anyone would have any difficulty at all
understanding that my statement referred to the values of variables
typed as "reference types" or "value types". I doubt anyone (except
perhaps you) took my paragraph to mean literally a type was being passed.

Pete
 
P

Peter Duniho

Christoph said:
[...]
It's a matter of definition, but the definition is specific and
well-known, and matches what David is describing.

Yes, as I said, David was completely right.
I was also right, though my wording was kind of misleading.

No, your wording was not simply "misleading". It was incorrect. You
wrote -- in regards to "reference types" -- that "instances of these
types, are passed by ref". "Passed by reference" has a very specific
meaning, and is independent of whether the type of the argument is a
reference type or not.
[...]
The name choice has nothing to do with passing by reference.

Of course the word "reference" has a similar meaning in both contexts.

Which helps explain why people often mistakenly conflate the two. But
it's important to remember that conflating the two is in fact incorrect.

Pete
 
R

Raj

Thanks indeed for all of your replies, precious time, patience and efforts!

We conlude that both formal and actual parameter share the same memory if we
invoke a function by ref

Is there a way to determine whether actual and formal paramters share the
same memory? I mean to ask, getting the address of formal paramter and actual
parameter.

Thank you very much

Regards
Raj

Peter Duniho said:
Christoph said:
[...]
It's a matter of definition, but the definition is specific and
well-known, and matches what David is describing.

Yes, as I said, David was completely right.
I was also right, though my wording was kind of misleading.

No, your wording was not simply "misleading". It was incorrect. You
wrote -- in regards to "reference types" -- that "instances of these
types, are passed by ref". "Passed by reference" has a very specific
meaning, and is independent of whether the type of the argument is a
reference type or not.
[...]
The name choice has nothing to do with passing by reference.

Of course the word "reference" has a similar meaning in both contexts.

Which helps explain why people often mistakenly conflate the two. But
it's important to remember that conflating the two is in fact incorrect.

Pete
.
 
P

Peter Duniho

Raj said:
Thanks indeed for all of your replies, precious time, patience and efforts!

We conlude that both formal and actual parameter share the same memory if we
invoke a function by ref

I wouldn't use the phrase "invoke a function by ref", and technically
the parameter as known by the method only "shares the same memory"
inasmuch as it's a reference to the same memory used by the variable
passed as the parameter. Specifically, in the context of the "actual
parameter" (the thing actually being passed), the name of that variable
is treated in a slightly different way from the name of the "formal
parameter" in the method itself.

But yes, I would say your summary is a reasonable way to describe
passing an argument by reference.
Is there a way to determine whether actual and formal paramters share the
same memory? I mean to ask, getting the address of formal paramter and actual
parameter.

They will share the same memory (in the sense described above) only if
the method parameter is passed by reference. I.e. with the "ref" or
"out" keyword. So, there should be no need to make such a comparison.
You can tell simply by looking at the method declaration whether a
parameter is passed by reference.

Pete
 
C

Christoph Basedau

Raj said:
Thanks indeed for all of your replies, precious time, patience and efforts!

We conlude that both formal and actual parameter share the same memory if we
invoke a function by ref

I'd say the actual parameter and the variable passed from the calling
context share the same memory, if the formal param is a ref-param.
Is there a way to determine whether actual and formal paramters share the
same memory? I mean to ask, getting the address of formal paramter and actual
parameter.


You mean something like the &-operator in C, or AddressOf in classic VB?
Afaics there is no such thing in managed code, cause there's no need
for knowing implementation details of memory management.
It should work in unsafe C#-code, since & is also the C#
"addressof"-operator.

Christoph
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top