By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
459,275 Members | 1,311 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 459,275 IT Pros & Developers. It's quick & easy.

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

P: n/a
This post was originally in the C# Corner site, but their server is
down. I'd like to see if this group can answer.

I program in C++ and am learning C#.

The issue is: why should anybody bother in C# with pass-by-reference
using the "ref" keyword or "out" for objects in a method parameter
list, when, after all, it appears in C# that for all intents and
purposes a reference is always being passed, rather than the real
object (with, it seems, the exception of data primitives like int,
which are not 'boxed').

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.

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?

Any comments? Why do we need 'ref' after all?

Fran

// start of console C# program

using System;

using System.Collections.Generic;

using System.Text;

namespace ConsoleApplication1

{
class Program

{

static void Main(string[] args)

{

MyObject A = new MyObject();

A.AMember = 1;

Methods.PassObjectByValue1(A);

Console.WriteLine(A.AMember);// 2 // That is, output is '2'

MyObject B = new MyObject();

B.AMember = 1;

Methods.PassObjectByValue2(B);

Console.WriteLine(B.AMember);// 1 //That is, output is '1' (not '2')

// while the above line 'proves' Brian's point, the 'change' below
(workaround) rebuts it?!

//////////////////////////////////////////////////

//change made here! "workaround"

B = Methods.PassObjectByValueTWO(B); //note use of "=" assignment
operator

//change object via pass by value? Yes! output is indeed
'2' not '1'

Console.WriteLine("B.AMember should equal TWO!: {0}",B.AMember);

// end of change made
/////////////////////////////////////////////////

/* rest of this listing shows how 'ref' superior when you want to
'change' the object--this is disputed above */

MyObject C = new MyObject();

C.AMember = 1;

Methods.PassObjectByRef1(ref C);

Console.WriteLine(C.AMember);// 2

MyObject D = new MyObject();

D.AMember = 1;

Methods.PassObjectByRef2(ref D);

Console.WriteLine(D.AMember);// 2

Console.ReadKey();

}

}

class MyObject

{

public int AMember;

}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// start of seperate source file now; // start of "Methods" class used
above

class Methods

{

public static void PassObjectByValue1(MyObject X)

{

// I can change the values of member of an

// parameter of a reference type passed by value

X.AMember = 2;

}

public static void PassObjectByValue2(MyObject X)

{

//I can't change the object

// THIS IS THE PART 'disputed' AND THE SUBJECT OF THE 'workaround'
above

X = new MyObject();

X.AMember = 2;
// the point by Brian being, that AMember = 2 here but still = 1
outside here

}

/////////////////////////////////////////// YES YOU CAN! ('workaround'
to above)
// add this function to the class Methods--

public static MyObject PassObjectByValueTWO (MyObject X)
{
//you can change the object!

MyObject WhyNot = new MyObject();
WhyNot.AMember = X.AMember + 1; //2

//now AMember is 2 here, and soon to be '2' outside too

return WhyNot; //returns object of type MyObject (this is the
key)
}

////////////////////////////////////////// END OF YES YOU CAN!

public static void PassObjectByRef1(ref MyObject X)

{

// I can change the values of member of an

// parameter of a reference type passed by ref

X.AMember = 2;

}

public static void PassObjectByRef2(ref MyObject X)

{

//I can also change the object that is referenced

X = new MyObject();

X.AMember = 2;

}

}

}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Aug 1 '07 #1
Share this Question
Share on Google+
13 Replies


P: n/a
Francois Appert <fr************@yahoo.comwrote:
This post was originally in the C# Corner site, but their server is
down. I'd like to see if this group can answer.

I program in C++ and am learning C#.

The issue is: why should anybody bother in C# with pass-by-reference
using the "ref" keyword or "out" for objects in a method parameter
list, when, after all, it appears in C# that for all intents and
purposes a reference is always being passed, rather than the real
object (with, it seems, the exception of data primitives like int,
which are not 'boxed').
Because passing a reference by value isn't the same as passing a
parameter by reference.

See http://pobox.com/~skeet/csharp/parameters.html

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Aug 1 '07 #2

P: n/a
Francois Appert wrote:
[...]
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?
I don't agree. How would you implement int.TryParse() without passing
by reference?

It is true that many uses of "ref" or "out" are unnecessary. That does
not, however, lead to the conclusion that "ref" and "out" are themselves
unnecessary.
[...]
> 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.
That's true. Usually you don't need to pass by reference, and so that's
why usually passing by reference isn't done. But that doesn't mean you
don't need passing by reference at all. It just means that the
occasions in which it's necessary or desirable are infrequent.

Pete
Aug 1 '07 #3

P: n/a
On Aug 1, 9:51 am, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
Because passing a reference by value isn't the same as passing a
parameter by reference.

Seehttp://pobox.com/~skeet/csharp/parameters.html

Thanks. I liked this explanation, albeit it took a while for it to
sink in: "There are four different kinds of parameters in C#: value
parameters (the default), reference parameters (which use the ref
modifier), output parameters (which use the out modifier), and
parameter arrays (which use the params modifier). You can use any of
them with both value and reference types. When you hear the words
"reference" or "value" used (or use them yourself) you should be very
clear in your own mind whether you mean that a parameter is a
reference or value parameter, or whether you mean that the type
involved is a reference or value type. If you can keep the two ideas
separated, they're very simple"

Fran

Aug 1 '07 #4

P: n/a
Jon Skeet [C# MVP] wrote:
Peter Duniho <Np*********@NnOwSlPiAnMk.comwrote:
>Francois Appert wrote:
>>[...]
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?
I don't agree. How would you implement int.TryParse() without passing
by reference?

It is true that many uses of "ref" or "out" are unnecessary. That does
not, however, lead to the conclusion that "ref" and "out" are themselves
unnecessary.

Well, they're not strictly necessary - you can cope without them, e.g.
by passing in an array of length 1.
My main point is that the statements made do not in and of themselves
lead to the conclusion that passing by reference is unnecessary. I have
been having difficulty following the exact meaning in Francois's posts,
but he _seems_ to me to be saying that where he sees the keyword "ref",
he feels you can just replace that by returning the value instead.
That's not true, at least not in all cases (e.g. TryParse()).

That said, while it can be truthfully said that the keywords themselves
are not strictly necessary, that's not the same as saying that passing
by reference is unnecessary. For example, that's essentially what
passing in an array of length 1 is doing, so using that as an example
doesn't prove that passing by reference is unnecessary; it just
demonstrates an alternative way to pass by reference.

And of course, one can degenerate the question further by suggesting
that C#, .NET, the Windows API, etc. are not, strictly speaking,
necessary. That is, it is trivially demonstrable that you can always
implement something that would naturally be passing by-reference as
something that effectively works like passing by-reference, but which is
technically speaking not passing by-reference.

My experience has been that most of the time I find myself putting a
by-reference parameter, it's because I'm being lazy and avoiding
restructuring the design so that it's better. But I do every once in
awhile find a situation in which passing by reference is truly useful.
Absolutely necessary? No...hardly anything we do in code is literally
"necessary". But I'm not sure there's much value in taking the pedantry
that far. :)

Pete
Aug 1 '07 #5

P: n/a
Jon Skeet [C# MVP] wrote:
Peter Duniho <Np*********@NnOwSlPiAnMk.comwrote:
>Francois Appert wrote:
>>[...]
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?
I don't agree. How would you implement int.TryParse() without passing
by reference?

It is true that many uses of "ref" or "out" are unnecessary. That does
not, however, lead to the conclusion that "ref" and "out" are themselves
unnecessary.

Well, they're not strictly necessary - you can cope without them, e.g.
by passing in an array of length 1.
My main point is that the statements made do not in and of themselves
lead to the conclusion that passing by reference is unnecessary. I have
been having difficulty following the exact meaning in Francois's posts,
but he _seems_ to me to be saying that where he sees the keyword "ref",
he feels you can just replace that by returning the value instead.
That's not true, at least not in all cases (e.g. TryParse()).

That said, while it can be truthfully said that the keywords themselves
are not strictly necessary, that's not the same as saying that passing
by reference is unnecessary. For example, that's essentially what
passing in an array of length 1 is doing, so using that as an example
doesn't prove that passing by reference is unnecessary; it just
demonstrates an alternative way to pass by reference.

And of course, one can degenerate the question further by suggesting
that C#, .NET, the Windows API, etc. are not, strictly speaking,
necessary. That is, it is trivially demonstrable that you can always
implement something that would naturally be passing by-reference as
something that effectively works like passing by-reference, but which is
technically speaking not passing by-reference.

My experience has been that most of the time I find myself putting a
by-reference parameter, it's because I'm being lazy and avoiding
restructuring the design so that it's better. But I do every once in
awhile find a situation in which passing by reference is truly useful.
Absolutely necessary? No...hardly anything we do in code is literally
"necessary". But I'm not sure there's much value in taking the pedantry
that far. :)

Pete
Aug 1 '07 #6

P: n/a
Jon Skeet [C# MVP] wrote:
Peter Duniho <Np*********@NnOwSlPiAnMk.comwrote:
>Francois Appert wrote:
>>[...]
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?
I don't agree. How would you implement int.TryParse() without passing
by reference?

It is true that many uses of "ref" or "out" are unnecessary. That does
not, however, lead to the conclusion that "ref" and "out" are themselves
unnecessary.

Well, they're not strictly necessary - you can cope without them, e.g.
by passing in an array of length 1.
My main point is that the statements made do not in and of themselves
lead to the conclusion that passing by reference is unnecessary. I have
been having difficulty following the exact meaning in Francois's posts,
but he _seems_ to me to be saying that where he sees the keyword "ref",
he feels you can just replace that by returning the value instead.
That's not true, at least not in all cases (e.g. TryParse()).

That said, while it can be truthfully said that the keywords themselves
are not strictly necessary, that's not the same as saying that passing
by reference is unnecessary. For example, that's essentially what
passing in an array of length 1 is doing, so using that as an example
doesn't prove that passing by reference is unnecessary; it just
demonstrates an alternative way to pass by reference.

And of course, one can degenerate the question further by suggesting
that C#, .NET, the Windows API, etc. are not, strictly speaking,
necessary. That is, it is trivially demonstrable that you can always
implement something that would naturally be passing by-reference as
something that effectively works like passing by-reference, but which is
technically speaking not passing by-reference.

My experience has been that most of the time I find myself putting a
by-reference parameter, it's because I'm being lazy and avoiding
restructuring the design so that it's better. But I do every once in
awhile find a situation in which passing by reference is truly useful.
Absolutely necessary? No...hardly anything we do in code is literally
"necessary". But I'm not sure there's much value in taking the pedantry
that far. :)

Pete
Aug 1 '07 #7

P: n/a
Sorry for the repeat posts. Learning a new (to me) newsreader's UI and
it's got some idiosyncrasies. :)

(I tried canceling the posts, but it's my experience that news servers
rarely honor cancel requests any more, so that's probably not going to
have any effect).
Aug 1 '07 #8

P: n/a
Peter Duniho <Np*********@NnOwSlPiAnMk.comwrote:

<snip>
That said, while it can be truthfully said that the keywords themselves
are not strictly necessary, that's not the same as saying that passing
by reference is unnecessary. For example, that's essentially what
passing in an array of length 1 is doing, so using that as an example
doesn't prove that passing by reference is unnecessary; it just
demonstrates an alternative way to pass by reference.
The pedant in me has to point out that that *isn't* passing by
reference by the strict definition - the definition using lvalues etc.
It's like C - it is strictly pass-by-value, but you can accomplish the
same goals as the ones pass-by-reference is used for by passing a
pointer by value.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Aug 1 '07 #9

P: n/a
Jon Skeet [C# MVP] wrote:
>[...]
For example, that's essentially what
passing in an array of length 1 is doing, so using that as an example
doesn't prove that passing by reference is unnecessary; it just
demonstrates an alternative way to pass by reference.

The pedant in me has to point out that that *isn't* passing by
reference by the strict definition
The pedant in me agrees with the pedant in you.

However, the fact remains that one is still essentially passing by
reference in that case, in a similar way that passing a pointer to a
pointer in C is just as much passing the pointer by reference as using
an actual reference is, even if it's technically not passing by reference.

IMHO, there are really two questions here. One, is the act of passing a
parameter in a way that allows for the modification of that parameter a
necessary feature? And two, is passing a parameter "by reference" a
necessary feature?

I allow that the strict, technical answer to the second is "no", but in
the sense that the answer to the first is "yes", if you don't have
something that is technically passing "by reference", you still need
_some_ mechanism that effectively does the same.

Software would be a LOT less interesting if a function being called had
no way to modify data outside of that function. :)

Pete
Aug 1 '07 #10

P: n/a
Peter Duniho <Np*********@NnOwSlPiAnMk.comwrote:
Jon Skeet [C# MVP] wrote:
[...]
For example, that's essentially what
passing in an array of length 1 is doing, so using that as an example
doesn't prove that passing by reference is unnecessary; it just
demonstrates an alternative way to pass by reference.
The pedant in me has to point out that that *isn't* passing by
reference by the strict definition

The pedant in me agrees with the pedant in you.
:)
However, the fact remains that one is still essentially passing by
reference in that case, in a similar way that passing a pointer to a
pointer in C is just as much passing the pointer by reference as using
an actual reference is, even if it's technically not passing by reference.
Agreed. I just think it helps to keep things *absolutely* straight when
discussing pass-by-reference - it's casual use of the terminology
("objects are passed by reference" etc) which leads to confusion, in my
experience.
IMHO, there are really two questions here. One, is the act of passing a
parameter in a way that allows for the modification of that parameter a
necessary feature? And two, is passing a parameter "by reference" a
necessary feature?

I allow that the strict, technical answer to the second is "no", but in
the sense that the answer to the first is "yes", if you don't have
something that is technically passing "by reference", you still need
_some_ mechanism that effectively does the same.
Software would be a LOT less interesting if a function being called had
no way to modify data outside of that function. :)
Possibly. It can't be *strictly* necessary, as you could always return
a complete copy of everything you want, with the client then taking
appropriate action. That would be pretty silly though.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Aug 1 '07 #11

P: n/a
Francois Appert wrote:
The issue is: why should anybody bother in C# with pass-by-reference
using the "ref" keyword or "out" for objects in a method parameter
list, when, after all, it appears in C# that for all intents and
purposes a reference is always being passed, rather than the real
object (with, it seems, the exception of data primitives like int,
which are not 'boxed').
They are handy in some special cases where return values are not
suitable.

For an example try coding a Swap method.

It is relative rare that they are needed. I did a quick search
in a dir with 727 .cs files and I only used them in 12 of them.
And half of that usage were DllImport og Win32 API functions
where it was not my choice.
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.

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
I think his example was not well suited.

You need a method with more than one out to make the point.

Arne
Aug 2 '07 #12

P: n/a
>Software would be a LOT less interesting if a function being called had
>no way to modify data outside of that function. :)

Possibly. It can't be *strictly* necessary, as you could always return
a complete copy of everything you want, with the client then taking
appropriate action. That would be pretty silly though.
I think you just insulted all the Functional Programmers in the world.
Aug 2 '07 #13

P: n/a
On Aug 2, 1:57 pm, "Ben Voigt [C++ MVP]" <r...@nospam.nospamwrote:
Possibly. It can't be *strictly* necessary, as you could always return
a complete copy of everything you want, with the client then taking
appropriate action. That would be pretty silly though.

I think you just insulted all the Functional Programmers in the world.
I suspect functional programmers have different idioms for coping with
the situation. I was meaning returning a value and then manually
copying all of the changed properties into the appropriate object. As
far as I'm aware that's *not* what functional programmers do :)

Jon

Aug 2 '07 #14

This discussion thread is closed

Replies have been disabled for this discussion.