Using ref

  • Thread starter Thread starter Arjen
  • Start date Start date
"What I showed is that whether
you pass a reference to an object by value or by reference in C#, in a
method/function, you can still do something 'permanent' to the object,
even when the method/function goes out of scope."


That is true, but not THE point. If your client lives, say, in Dallas, then,
when you want to reach it, you look where? in Dallas, no! if you are in
Seattle, you look at your cardfile holding your clients addresses. Now, if
one of your buddy (procedure), living in New York, ask to contact the said
client, you have two options: make a copy of your cardfile and 'pass' it to
him, that is 'by value', or you cant 'rent' him, for a while, your cardfile,
that will be 'passed by reference'. In both case, your New York buddy can
reach your client, in Dallas, and he can change your client to a not-client
anymore, quite permanently, sure, but, and there is a but, in the last case,
it can do much more, he can screw your cardfile too. And NEVER you ever
"passed" (ouch) the client it-self to your buddy.



Vanderghast, Access MVP
 
Peter Duniho said:
The fact that the value you're passing is a reference does not make the
parameter a "by reference" parameter, nor does it mean that the object is
passed by reference.

IMHO, Jon's article does in fact explain this.

Pete

Yes it does, and some days I'm slower than others. It didn't sink in for me
until Jon put up the Swap example.

- Steve
 
Peter said:
It's unfortunate that you would continue to refuse to change your view on
the matter, but the worst part is your insistence on continuing to
promulgate your view as the correct one.

I have no problem discussing things with people, but I don't like it (and I
think it shows your true colors - others have mentioned this too) when you
start trying to spread BS about people. I'm not trying to 'promulgate' my
view as the correct one, look what I said in my posts:

"I know that most of the literature out there agrees with your point of
view."
"Jon, I totally 'see' you view on this (which seems to be consistent with
many/most others - i.e. I acknowledge that I am in the minority here)."

Then you accuse me of not posting code. Without trying to sound sarcastic,
I assumed someone of your knowledge and experience (I mean this, I'm not
being sarcastic) would know how to write the following code, compile and run
ildasm and see the IL:

class Class1
{
[STAThread]
static void Main(string[] args)
{
new Class1 ().Go();
}

void Go ()
{
string s = "C#";

Method1 (s);
Method2 (ref s);

}

void Method1 (string s)
{}

void Method2 (ref string s)
{}
}


Hilton
 
Yes it does, and some days I'm slower than others. It didn't sink in for me
until Jon put up the Swap example.

Then you'll love my example even more. And Jon's Swap example had a
typo in it (that I corrected).

Remember the rules of Ray then: for optimal performance, use Ref.
For stuff that's primitive, use non-Ref (Swap by value). For objects
(including arrays, strings [all forms, including String,
StringBuilder], user defined classes), use ref only if "new" is
present in the function/method, or only if you are 'redirecting' the
object like with "Swap", otherwise it's OK to use pass-by-value.

RL
 
Hilton--FYI Peter is a bit dogmatic, been that way for years, but he
is a useful reference here. We see your point, but I say give it a
rest. But for Jon and Peter, we wouldn't have decent programmers
working for free.

RL

[C# "newbie" MVP]
 
"What I showed is that whether
you pass a reference to an object by value or by reference in C#, in a
method/function, you can still do something 'permanent' to the object,
even when the method/function goes out of scope."

That is true, but not THE point.

Thanks Michel Walsh! "That is true..."; I take that as a sort of
newbie moral victory of sorts, kinda, sorta.
If your client lives, say, in Dallas, then,
when you want to reach it, you look where? in Dallas, no! if you are in
Seattle, you look at your cardfile holding your clients addresses. Now, if
one of your buddy (procedure), living in New York, ask to contact the said
client, you have two options: make a copy of your cardfile and 'pass' it to
him, that is 'by value', or you cant 'rent' him, for a while, your cardfile,
that will be 'passed by reference'. In both case, your New York buddy can
reach your client, in Dallas, and he can change your client to a not-client
anymore, quite permanently, sure, but, and there is a but, in the last case,
it can do much more, he can screw your cardfile too. And NEVER you  ever
"passed" (ouch) the client it-self to your buddy.

So are you saying 'pass-by-value' is like 'constant' in C++ (which to
my newbie knowledge C# lacks) in that you can safely pass an object to
a function so it cannot be manipulated to change the original? If so,
please let me know how to do that, since honestly once I learned C# I
have yet to find how you can make a function/method take a 'read only'
copy of a class (not a primitive type, but of a class). In fact,
Googling this confirmed this fact (see below). So I don't see how
pass-by-value is any 'safer' (or read-only) than 'pass-by-value' for a
class passed.

RL

Googling on 'const', note the **** text ****--RL

The const keyword only applies to variables, which MSDN calls
“fields”. A field with the const keyword indicates that the field
cannot be changed. The value of the field must be initialized in the
declaration. Interestingly, attributes cannot be declared as const,
and furthermore, attributes referring to const fields can only have
getters, not setters.

****In C++, the const keyword was also used to indicate that the
method did not modify any variables:****
void Foo() const;

****or that the method returned a reference that could not be
modified:****
const int& Foo();

or that the parameter being passed as a reference could not be
modified by the method:
void Foo(const int& i);

which could lead to some ridiculous but valid statements:
const int& Foo(const int& i) const;

Happily, C# treats the keyword const with only one meaning.

Declaring fields as const protects both you and other programmers from
accidentally changing the value of the field. Also note that with
const fields, the compiler performs some optimization by not declaring
any stack space for the field.

Furthermore, const can only be applied to intrinsic types. You can’t
say:
const HasConstField hcf2=new HasConstField();
 
They are _not_ "doing EXACTLY the same thing".  The C# version is passing  
the address of a variable that contains a reference to an object, while  
the C version is passing the address of a variable that contains the  
object itself.

That's pretty slick, and you have to acknowledge that people coming
from a non-managed, non-automatic garbage collected, non-Intermediate
language background like C or C++ (classic version) might not grasp
this subtitety, PD.
You remind me of the people who continue to cling to the idea that Iraq  
had something to do with the 9/11 attacks and that Hussein was hiding  
weapons of mass destruction somewhere in his country, in spite of  
absolutely no evidence in support of those ideas and in spite of volumes  
of evidence to the contrary.

Well, if you define chemical weapons as "WMD" then arguably S. Hussein
had this capability, or he did have this capability, or he could
quickly acquire this capability, though your point is understood. And
let's not get politics involved, shall we? We're trying to keep this a
flame free and troll free thread.

In other words, you've decided on your dogma and no amount of actual facts  
will have any effect on your beliefs.

That's an unfortunate characteristic for any human being, but it's  
especially problematic for someone in a field like programming.  Computers  
don't adjust themselves to accommodate your way of thinking.  No matter 
how much you wish for C to have pass by reference, and no matter how much 
you wish for C#'s pass by value to be the same as C#'s pass by reference, 
it simply will not be.

We can will it away, Nietzsche style. Remember, F. Nietzsche did not
believe there was one objective "TRUTH" out there, but many points of
view. Put another way: if a competent scientist publishes a paper on
evolution that is correct in terms of received wisdom, but privately
believes in Creationism, does that make his paper unacceptable? No.
And if this poster believes that C and C#.NET pass-by-reference the
same way, which they don't according to your world view, but writes
code that works, is that unacceptable? Probably not unless you are
teaching or writing a paper on C. Sci theory. In short, William
James '19th century pragmatism' as it applies to philosophy probably
overrules whatever 'objective' objections you might have to the
posters 'wrong' world view. In short, whatever works, works,
regardless of the 'Truth' of the matter.

RL

[C# troll who makes occasionally incisive comments MVP]
 
Jon wrote:
Hilton said:
You're only looking at the calling side. Look at the declaring side.
In C, you're declaring the parameter with a different type - a pointer
type. You then have to *use* that parameter differently as well,
explicitly dereferencing etc.
In C#, you declare that the parameter is passed by reference, but the
actual parameter has the same original type, and can be used within
the method as if it were any other variable of that type.

So, if I understand you correctly, the determination of "pass by value" or
"pass by reference" is based on syntax and not functionality (here I mean
what actually gets passed etc). Please see my code below:

Where exactly are the benefits of using the inaccurate terminology?

None, I don't like to.


OK, back to basics and as simple as I can make it. Let use the C# code:

void Go ()
{
int x = 10;

Method (ref x);
}

void Method (ref int y)
{
y = 20;
}

I am claiming that this is exactly the same as the C code that has "Method
(&x)" (caller) and "Method (int *py)" (callee). All that is happening is
that the compiler is hiding the 'ugliness' from you, so that when you write
"y=20" (above), it really does a "*py= 20". So IMHO, it is just some
language/compiler smoke and mirrors, the *same thing* is happening under the
covers. But don't take my word for it, let's look at the IL:

The Caller IL is:

..method private hidebysig instance void Go() cil managed
{
// Code size 12 (0xc)
.maxstack 2
.locals init ([0] int32 x)
IL_0000: ldc.i4.s 10
IL_0002: stloc.0
IL_0003: ldarg.0
IL_0004: ldloca.s x
IL_0006: call instance void Test.Class1::Method(int32&)
IL_000b: ret
} // end of method Class1::Go

Kinda curious that Microsoft label the call as "int32&", anyway... This is
why I mentioned "ldloca.s" in an earlier post - according to Microsoft's
documentation, this "Loads the address of the local variable at a specific
index onto the evaluation stack, short form." So it is passing the address
of "x", exactly the same as our C code. Now, let's look at the Callee IL:

..method private hidebysig instance void Method(int32& y) cil managed
{
// Code size 5 (0x5)
.maxstack 2
IL_0000: ldarg.1
IL_0001: ldc.i4.s 20
IL_0003: stind.i4
IL_0004: ret
} // end of method Class1::Method

Again, I have to smile at the "&" in the first line. According to
Microsoft's documentation, stind.i4 "Stores a value of type int32 at a
supplied address." which is exactly the same (functionally) as the C code's
"*py = 20".

So, here we have C# and C code, the IL, Microsoft documentation, and I have
(hopefully) shown that the code is functionality exactly the same (by this I
mean what gets passed/received/used).

Jon, is this C# code "pass by value" or "pass by reference"? By your
earlier claims, the C code is "pass by value". So either:

1. The C# is "pass by value" in which case "ref" does not mean "pass by
reference", or
2. The C# code is "pass by reference" even though exactly the same as its C
counterpart, just a different syntax, or
3. The whole "pass by value/reference" claim is a syntactic claim and not a
functional/performance claim.

Hilton
 
I don't see it as the same thing, no, since my New York buddy CAN still
write over the cardfile, a copy, I sent him (for whatever reason he may have
to write over it, such as re-using the cardfile to store another address).
The safeguard is that doing so, he won't destroy MY cardfile content.


Vanderghast, Access MVP

On Jul 3, 8:42 am, "Michel Walsh"

(...)
So are you saying 'pass-by-value' is like 'constant' in C++ (which to
my newbie knowledge C# lacks) in that you can safely pass an object to
a function so it cannot be manipulated to change the original?
(...)
 
Hilton said:
So, if I understand you correctly, the determination of "pass by value" or
"pass by reference" is based on syntax and not functionality (here I mean
what actually gets passed etc).

It's based on how the argument is evaluated, and the receiving
parameter.

For pass by value, the argument can be any expression of the
appropriate type. The receiving parameter starts off with the value of
that expression.

For pass by reference, the argument has to be an lvalue (an expression
categorised as a variable in C#). The parameter is aliased with that
lvalue.
Please see my code below:



None, I don't like to.

You've admitted that your use of terminology is inaccurate several
times, so if you don't like it, just stop.
OK, back to basics and as simple as I can make it. Let use the C# code:

void Go ()
{
int x = 10;

Method (ref x);
}

void Method (ref int y)
{
y = 20;
}

I am claiming that this is exactly the same as the C code that has "Method
(&x)" (caller) and "Method (int *py)" (callee).

The *effect* is the same, but look at the type of py in C and y in C#.
In C, you declare that the variable is a pointer type, and have to
explicitly dereference it in order to change the value the caller sees.
Instead of that, you could change the value of the parameter itself to
be a completely different int*. The parameter just happens to start off
with a value which has been evaluated as the address of x.
All that is happening is
that the compiler is hiding the 'ugliness' from you, so that when you write
"y=20" (above), it really does a "*py= 20". So IMHO, it is just some
language/compiler smoke and mirrors, the *same thing* is happening under the
covers. But don't take my word for it, let's look at the IL:

The Caller IL is:

.method private hidebysig instance void Go() cil managed
{
// Code size 12 (0xc)
.maxstack 2
.locals init ([0] int32 x)
IL_0000: ldc.i4.s 10
IL_0002: stloc.0
IL_0003: ldarg.0
IL_0004: ldloca.s x
IL_0006: call instance void Test.Class1::Method(int32&)
IL_000b: ret
} // end of method Class1::Go

Kinda curious that Microsoft label the call as "int32&", anyway...

Not really - that's C++ syntax for pass by reference.
This is
why I mentioned "ldloca.s" in an earlier post - according to Microsoft's
documentation, this "Loads the address of the local variable at a specific
index onto the evaluation stack, short form." So it is passing the address
of "x", exactly the same as our C code. Now, let's look at the Callee IL:

.method private hidebysig instance void Method(int32& y) cil managed
{
// Code size 5 (0x5)
.maxstack 2
IL_0000: ldarg.1
IL_0001: ldc.i4.s 20
IL_0003: stind.i4
IL_0004: ret
} // end of method Class1::Method

Again, I have to smile at the "&" in the first line. According to
Microsoft's documentation, stind.i4 "Stores a value of type int32 at a
supplied address." which is exactly the same (functionally) as the C code's
"*py = 20".

So, here we have C# and C code, the IL, Microsoft documentation, and I have
(hopefully) shown that the code is functionality exactly the same (by this I
mean what gets passed/received/used).

I've repeatedly said that you can *simulate* pass by reference in C.
You can achieve the same effects. But from a language terminology point
of view, the parameter has *not* been passed by value.
Jon, is this C# code "pass by value" or "pass by reference"?

The C# code is pass by reference. The variable x has been passed by
reference.
By your earlier claims, the C code is "pass by value".

Absolutely. The *address* of x has been passed by value.
So either:

1. The C# is "pass by value" in which case "ref" does not mean "pass by
reference", or
2. The C# code is "pass by reference" even though exactly the same as its C
counterpart, just a different syntax, or
3. The whole "pass by value/reference" claim is a syntactic claim and not a
functional/performance claim.

It's a semantic claim. It's the meaning of the parameter / argument.

It really is pretty simple. Any time you see a method call without a
ref/out modifier, that's pass by value. That's why it's called a value
parameter in the specification.

The purpose of agreeing terminology is to make communication easier.
You've acknowledged in various posts that you're going against the
accepted terminology. You haven't given any counterargument to my
claims that using your meanings causes confusion and leads to a much
more complicated mental model in terms of garbage collection,
assignments etc. All of this, and yet you claim you don't like to use
inaccurate terminology - so why not just accept the terminology of the
specification, other languages, and computer science in general?
 
Peter said:
Hilton wrote:

It's not "exactly the same". There are important differences between the
two that you are ignoring.

They both pass an address, they both store 20 to the memory pointed to by
that address. What important differences am I ignoring?

It is a critically important description of how the _language_ works.
Just because you can get the compiled result to accomplish the same thing,
that doesn't mean that the _language_ concepts are the same.

They don't simply accomplish the same thing, they are doing the same thing.
Does the fact that you keep going back to the language (and its syntax) mean
that you agree with me that this is all about syntax? Probably not. :)

Again, two pieces of code doing the same thing yet one is pass-by-value, the
other is pass-by-reference? (as you confirmed)

If we're talking about how it 'looks' (i.e. syntax), then I agree with you
and Jon (as I stated before). But to me, the whole concept is not the
pretty smoke and mirrors on the surface, but what is actually happening -
that's why I posted the code, IL etc.

Hilton
 
Hilton said:
They both pass an address, they both store 20 to the memory pointed to by
that address. What important differences am I ignoring?

The fact that the type of the parameter in the C version is a pointer
type, as is the argument - whereas in the C# version the type is just a
normal type. The fact that in the C version you could pass in any
pointer, including NULL - and treat it just like any other pointer,
beyond just dereferecing it to change the original variable's value.
They don't simply accomplish the same thing, they are doing the same thing.
Does the fact that you keep going back to the language (and its syntax) mean
that you agree with me that this is all about syntax? Probably not. :)

Not syntax, language definitions.
Again, two pieces of code doing the same thing yet one is pass-by-value, the
other is pass-by-reference? (as you confirmed)

They are achieving the same effect. In Java you can achieve a similar
effect by creating a single-element array, passing that (to a method
which has to take an array of the right type) and then changing that
element within the method.

Would you call that workaround "pass by reference" as well, just
because it can achieve the same eventual effect?
If we're talking about how it 'looks' (i.e. syntax), then I agree with you
and Jon (as I stated before). But to me, the whole concept is not the
pretty smoke and mirrors on the surface, but what is actually happening -
that's why I posted the code, IL etc.

It's not just syntax, it's the behaviour which is defined by the
language specification.
 
Hilton said:
Jon, I totally 'see' you view on this (which seems to be consistent with
many/most others - i.e. I acknowledge that I am in the minority here).

It is important to use standard terminology.

You could design the foobar language where you define that:
7 * 3 is 4
* is the add operator
but noone will be able to understand what is going on, because
+-* and add subtract multiply has meanings.

The terms pass by value and pass by reference has meanings as
well.

Use them instead of creating confusion with your own definitions.

Arne
 
raylopez99 said:
Remember the rules of Ray then: for optimal performance, use Ref.

Not. You use ref or not ref based on what fits the problem, not what
you think may perform best (and there are no guarantee that ref will
perform best).

Arne
 
Peter said:
We're not. There are fundamental differences in the way the parameters
are used when you have a language that actually supports passing "by
reference", as compared to a language that does not.

That said, I'm done trying to help you understand. Every time you think
you've come up with an example that illustrates why things are the same,
we point out why the example is wrong. You either ignore those points
altogether (and why not? why bother to listen to any fact that conflicts
with your own view?), or you come up with some new example that is
similarly flawed (repeating the cycle).

You obviously aren't interested in learning something new. You reject
anything that confronts your own pre-established beliefs, and frankly, I
find religious debates pointless.

At least for the time being, this thread has sufficient content to avoid
any naïve reader thinking that you actually know what you're talking
about, and that's good enough for me. As I said, I don't really care what
_you_ believe...I just don't want anyone else thinking you're right. I'm
sure that goal has been accomplished.

Just to beat a dead horse and debunk your usual "Hilton's own view" opinion,
I did a quick search and found stuff on multiple university web sites and in
books teaching/showing "pass by reference" using C - here are some links,
but "pass by reference" using C is in many many many places:

(note the title)
http://www.cs.princeton.edu/~lworthin/126/precepts/pass_val_ref.html - "With
pointers, we can pass the values 'by reference.' Passing by reference means
that we'll pass the addresses of the variables instead of the values."

It's silly getting all heated up about these discussions. Again, your view
(which is consistent with Jon and many others) is that it is how it looks
and works from the source code point of view - fine, I have no problem with
that. But to me (and many others), that is mostly academic, what concerns
me is what is actually happening - i.e. is the entire array or just a
pointer/reference to the array being passed.

Having said that, I understand your frustration with another point of view.
I don't like hearing the media say that a plane stalled when its engine
stopped. Although we can blame the Wright brothers for this one. :)

Hilton
 
Peter Duniho said:
And to Steve: I _strongly_ recommend you use Google Groups to review
previous discussions and posts by Ray. You should take everything you
read on the Internet with a grain of salt anyway, but in this case you can
make a decision for yourself as to what advice is likely to be correct,
useful, etc. by examining previous contributions and seeing if they look
like they were written by someone you'd consider reliable.

It's like you're inside my head...
;-)

- Steve
 
It's silly getting all heated up about these discussions.

No, I don't believe it is. I've seen the results of people being loose
with terminology: other people get confused. If you say that reference
types are pased by reference by default, people who understand the
true meaning of pass by reference *will* get confused. I've seen it
happen in groups time and time again.
 Again, your view
(which is consistent with Jon and many others) is that it is how it looks
and works from the source code point of view

Not just from the source code point of view - from the *language*
point of view. It's how the language defines the behaviour.
- fine, I have no problem with
that.  But to me (and many others), that is mostly academic, what concerns
me is what is actually happening - i.e. is the entire array or just a
pointer/reference to the array being passed.

But the beauty of the accurate way of talking about things is that it
not only gets "what is actually happening" right, but it gives a
consistent view across the whole language. It also has the benefit of
being right by the specification :)

If we can't convince you that the inaccurate terminology is worth
avoiding just for the sake of correctness and avoiding confusing
others, perhaps I can present a different reason: your terminology
just won't stand up in the face of some odd situations. Consider this
code:

using System;
using System.Text;

struct Foo
{
public int x;
public StringBuilder sb;

public Foo(int x)
{
this.x = x;
sb = new StringBuilder();
}
}

class Test
{
static void Main()
{
Foo f = new Foo(5);
Method(f);
Console.WriteLine(f.x);
Console.WriteLine(f.sb);
}

static void Method(Foo foo)
{
foo.x = 10;
foo.sb.Append("Hi");
}
}

The result is 5 and then "Hi". The accurate view copes with this very
simply - when Method is called, f is passed by value - a copy is made
of both fields, one of which is a reference. The change to foo.x in
Method is therefore only made to the copy - but the references foo.sb
and f.sb are identical - they refer to the same object, so changes
made to that object (not to the sb variable itself) are still visible
after the call.

Now, I don't believe you'll be able to explain that in your overly
simplistic view of pass by value vs pass by reference - at least not
without making it pretty convoluted. At some point you'll have to come
back to the fact that sb isn't an object, it's a reference. When
you've gone that far, the next logical step is to look at exactly what
gets passed when you *just* have a StringBuilder.

In short, using the accurate terminology has these benefits:
1) It avoids confusing people
2) It's consistent across all situations
3) It agrees with the spec, which is meant to be our means of
communicating

Which of these benefits can you deny? If you don't deny them, why do
you ignore them? What benefit does your terminology have over them?

Jon
 
It's silly getting all heated up about these discussions.  Again, your view
(which is consistent with Jon and many others) is that it is how it looks
and works from the source code point of view - fine, I have no problem with
that.  But to me (and many others), that is mostly academic, what concerns
me is what is actually happening - i.e. is the entire array or just a
pointer/reference to the array being passed.

I think it's the pointer/reference to the array, since it's faster.
Like you say, or so it seems, "behind the scenes" the effect is the
same. But, Jon, Arne and Pete are correct because we deal with the
source code, not the IL stuff 'behind the scenes'.

Put another way: 'behind the scenes' you can, at the machine code
level, say that C and C++ and Pascal and Visual Basic are "all the
same", because the microprocessor uses op codes in 1's and 0's that
push, pop, fetch, etc, instructions and data 'the same way'. But that
distinction blurs the real differences between the languages.

RL
 
And to Steve: I _strongly_ recommend you use Google Groups to review  
previous discussions and posts by Ray.  You should take everything you  
read on the Internet with a grain of salt anyway, but in this case you can  
make a decision for yourself as to what advice is likely to be correct,  
useful, etc. by examining previous contributions and seeing if they look  
like they were written by someone you'd consider reliable.

No, you can also look at the code I post you blowhard.
And for what it's worth, the same thing is true for any of the rest of  
us.  You shouldn't accept any of our statements without at least some  
critical consideration, and I'm not going to try to convince you that Jon,  
I, or anyone else is more or less reliable than someone else.  

That's right, you're slightly more reliable than me, but I back up my
stuff with code and you just rely on your authoritative sounding
posts.

You can  
make an informed decision yourself just by looking at past contributions  
to the newsgroup.

Right. And I deliver. I even have posted stuff on depthwise
traversed n-ary trees that I've never seen before on the net. BTW,
the library of C# sucks when it comes to trees--really primitive, I
don't think they even have a black-red binary balanced tree, last I
checked.

RL
 
My point is that the C# call "method (ref x)" is defined by
you/Jon/community as being pass by reference, yet the C call "method (&x)"
is defined by you/Jon/community as being pass by value - they're doing
EXACTLY the same thing.  Both simply take the address of x and pass it
along.  Does a prettier syntax changes the entire concept?   And if
Microsoft has used "&" instead of "ref" in its definition of the C#
language, would that now mean that the C# call "method (&x)" was now passby
value???

Pete, really, I don't want to spend more of your time or my time on this.
In my mind (which I agree probably doesn't fit the pure definition of the
pass-by definitions), if I pass a reference or pointer to my chunk of data,
I'm passing by reference (the focus being on the data, not the actual
parameter).  I think millions of other people think that way too since
pass-by-reference has been taught for decades when discussing C, but
apparently that capability never existed.

Where the difference is really visible is when you use C++/CLI:

void TakesObjectReferenceByValue(Object^ reference);
void TakesObjectReferenceByReference(Object^% reference);

Note that C++/CLI explicitly spells out the "reference to .." part of
an object reference type as "^" - only they call it a "handle" there.
On the other hand, to declare a by-reference parameter, you use "%",
which is called a "reference" there. It is really unfortunate that C#
designers chose to overload the term "reference" for both object
references and byref arguments. Also, I think that, if the nature of
object references would be explicitly spelt out in the code (as in C++/
CLI), it would make it easier to wrap one's head around the concept of
"passing an object reference by reference".

This distinciton is visible all the way down to CLI level, by the way.
The canonical terms there are: "reference" for an object reference,
and "managed pointer" for what is "ref" in C# and "%" in C++/CLI.

It is conventional, therefore, to only say that an argument is "passed
by reference" if the actual type of the argument is a CLI managed
pointer; otherwise, it is "passed by value".

In a plain C++ context, by the way, the same distinction exists. A
method taking a pointer to int is usually spoken of as "taking a
pointer by value". A method taking a reference, on the other hand, is
"taking an integer by reference":

void TakesIntPointerByValue(int* p);
void TakesIntByReference(int& p);
void TakesIntPointerByReference(int*&p );
 

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

Back
Top