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

pass by value vs. by reference question

P: n/a
I'm reading the MS press C# book and there seems to be a contradiction.
Please tell me which one is correct, 1 or 2.
Thanks!
Jeff

1. First it gives the code below saying that it prints 0 then 42.
They say that 42 is printed the second time since the value was wrapped in a
class and therefore became passed by reference.
(sorry for any typos I am a newbie here ;-)

class Application
{
static void Entrance()
{
WrappedInt wi = new WrappedInt();
Console.WriteLine(wi.Number); //This one prints 0
they say...
Pass.Reference(wi);
Console.WriteLine(wi.Number) //And this one
prints 42.
}
}

class WrappedInt
{
public int Number;
}

class Pass
{
public static void Reference(WrappedInt param)
{
param.Number = 42;
}
}

--------------------------------

2. Then it goes on to say that whether it is passed by value or reference,
the original arguement is unchanged unless you use 'ref' or 'out'.
So what gives? Which is correct, 1 or 2? If 2 is correct, then the example
they gave in 1 shouldn't be valid right? I may be missing something you
would find obvious.

Thanks for any explanations!
Nov 16 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
The first one does print 0, and the second does print 42. And both 1 and 2
are technically correct.

Explanation:

The key to this is understanding the difference between a reference type an
a value type.

Anything that you define as a class (like the WrappedInteger class) is a
reference type. That means that in memory, it never really "lives" inside a
variable. Rather, any variables that are of type WrappedInteger, are
"references" (think "pointer" -- not exactly like a C++ pointer, but along
those lines).

So, when you set wi = new WrappedInt();

Whats really happening is that a WrappedInt() object is being created
somewhere in memory, and then a reference (kinda like a pointer) to that
object is being stored in the variable wi.

So if you do this:
WrappedInt wi = new WrappedInt();
WrappedInt wi2 = wi;

wi2 and wi are both referencing (pointing to) the same object instance. So,
if you do this:
wi.Number = 10;
w2.Number = 20;
Console.WriteLine(wi.Number)

You get "20", because wi and w2 are both pointing to exactly the same
location in memory.

Now, in contrast, lets look at a value type. your primitives like
ints/floats/bools (full list in the help) are value types, as is anything
that you define as a struct. That means that when you assign one to the
other it is copied in memory -- it really does "live" in the variable.

So:
int x = 5;

The value 5 is deposited in the memory location for x.

int y = x;
x = 10;

y is 5, and x is a 10.

the 5 is copied from x to y, and it is now a copy -- y is independent of x
so when you change x, it only affects x. This should be very familiar
ground -- its the behavior you would expect when dealing with ints in most
common languages (VB 6, Delphi, etc)

Now, lets look at their example:
when they call Pass.Reference(wi), you are passing the value in wi, which is
really just a pointer to an object in memory. When the code in reference
sets Param.Number:
param.Number = 42;
It is getting the reference (pointer) location from param and runnign out
into memory to access the .Number member. It is accessing the same object
in memory as wi, and setting its Number property = 42, so that set "counts"
inside of Main because you passed a reference type.

So, right now it looks like #1 was right.

Now, why is #2 right?

Well, when you call Pass.Reference(wi), you are passing the reference (the
pointer in wi) to the ReferenceMethod by value. If reference tries to
modify the actual value of the pointer (by assigning it to another object),
it will not affect the variable wi in the calling method.

Here's what I mean:
WrappedInt wi = new WrappedInt();
wi.Number = 5;
Pass.Reference(wi);
Console.WriteLine(wi.Number);
// prints "5"

public class Pass
{
public static void Reference(WrappedInt param)
{
// instead of changing .Number, lets try reassign to a new object
// note the difference: I'm reassining param rather than one
// of its members
param = new WrappedInt()
param.Number = 10;
}
}

On the other hand, if you modify Referenct to accept param as a ref
parameter, and then you pass wi as a ref:
Pass.Reference(ref wi)
Console.WriteLine(wi.Number) will print a 10;

Since you passed wi by reference, the Reference method changed the location
in memory that it was pointing to such that it is pointing to the new object
instance. You now don't have any way to access the WrappedInt object that
you originally created in main, and it will be garbage collected and removed
from memory.
I know that was a really long, somewhat contorted explanation. I hope it
helped.

"z_learning_tester" <so*****@microsoft.com> wrote in message
news:mfpAc.66015$0y.328@attbi_s03...
I'm reading the MS press C# book and there seems to be a contradiction.
Please tell me which one is correct, 1 or 2.
Thanks!
Jeff

1. First it gives the code below saying that it prints 0 then 42.
They say that 42 is printed the second time since the value was wrapped in a class and therefore became passed by reference.
(sorry for any typos I am a newbie here ;-)

class Application
{
static void Entrance()
{
WrappedInt wi = new WrappedInt();
Console.WriteLine(wi.Number); //This one prints 0 they say...
Pass.Reference(wi);
Console.WriteLine(wi.Number) //And this one
prints 42.
}
}

class WrappedInt
{
public int Number;
}

class Pass
{
public static void Reference(WrappedInt param)
{
param.Number = 42;
}
}

--------------------------------

2. Then it goes on to say that whether it is passed by value or reference,
the original arguement is unchanged unless you use 'ref' or 'out'.
So what gives? Which is correct, 1 or 2? If 2 is correct, then the example
they gave in 1 shouldn't be valid right? I may be missing something you
would find obvious.

Thanks for any explanations!

Nov 16 '05 #2

P: n/a
OK, had to read that a *few* times.
But I've got it now.

It really took all of those examples for me to put it together- so thanks
for taking the time!

"J.Marsch" <je****@ctcdeveloper.com> wrote in message
news:eO*************@TK2MSFTNGP09.phx.gbl...
The first one does print 0, and the second does print 42. And both 1 and 2 are technically correct.

Explanation:

The key to this is understanding the difference between a reference type an a value type.

Anything that you define as a class (like the WrappedInteger class) is a
reference type. That means that in memory, it never really "lives" inside a variable. Rather, any variables that are of type WrappedInteger, are
"references" (think "pointer" -- not exactly like a C++ pointer, but along
those lines).

So, when you set wi = new WrappedInt();

Whats really happening is that a WrappedInt() object is being created
somewhere in memory, and then a reference (kinda like a pointer) to that
object is being stored in the variable wi.

So if you do this:
WrappedInt wi = new WrappedInt();
WrappedInt wi2 = wi;

wi2 and wi are both referencing (pointing to) the same object instance. So, if you do this:
wi.Number = 10;
w2.Number = 20;
Console.WriteLine(wi.Number)

You get "20", because wi and w2 are both pointing to exactly the same
location in memory.

Now, in contrast, lets look at a value type. your primitives like
ints/floats/bools (full list in the help) are value types, as is anything
that you define as a struct. That means that when you assign one to the
other it is copied in memory -- it really does "live" in the variable.

So:
int x = 5;

The value 5 is deposited in the memory location for x.

int y = x;
x = 10;

y is 5, and x is a 10.

the 5 is copied from x to y, and it is now a copy -- y is independent of x
so when you change x, it only affects x. This should be very familiar
ground -- its the behavior you would expect when dealing with ints in most
common languages (VB 6, Delphi, etc)

Now, lets look at their example:
when they call Pass.Reference(wi), you are passing the value in wi, which is really just a pointer to an object in memory. When the code in reference
sets Param.Number:
param.Number = 42;
It is getting the reference (pointer) location from param and runnign out
into memory to access the .Number member. It is accessing the same object
in memory as wi, and setting its Number property = 42, so that set "counts" inside of Main because you passed a reference type.

So, right now it looks like #1 was right.

Now, why is #2 right?

Well, when you call Pass.Reference(wi), you are passing the reference (the
pointer in wi) to the ReferenceMethod by value. If reference tries to
modify the actual value of the pointer (by assigning it to another object), it will not affect the variable wi in the calling method.

Here's what I mean:
WrappedInt wi = new WrappedInt();
wi.Number = 5;
Pass.Reference(wi);
Console.WriteLine(wi.Number);
// prints "5"

public class Pass
{
public static void Reference(WrappedInt param)
{
// instead of changing .Number, lets try reassign to a new object
// note the difference: I'm reassining param rather than one
// of its members
param = new WrappedInt()
param.Number = 10;
}
}

On the other hand, if you modify Referenct to accept param as a ref
parameter, and then you pass wi as a ref:
Pass.Reference(ref wi)
Console.WriteLine(wi.Number) will print a 10;

Since you passed wi by reference, the Reference method changed the location in memory that it was pointing to such that it is pointing to the new object instance. You now don't have any way to access the WrappedInt object that
you originally created in main, and it will be garbage collected and removed from memory.
I know that was a really long, somewhat contorted explanation. I hope it
helped.

"z_learning_tester" <so*****@microsoft.com> wrote in message
news:mfpAc.66015$0y.328@attbi_s03...
I'm reading the MS press C# book and there seems to be a contradiction.
Please tell me which one is correct, 1 or 2.
Thanks!
Jeff

1. First it gives the code below saying that it prints 0 then 42.
They say that 42 is printed the second time since the value was wrapped in
a
class and therefore became passed by reference.
(sorry for any typos I am a newbie here ;-)

class Application
{
static void Entrance()
{
WrappedInt wi = new WrappedInt();
Console.WriteLine(wi.Number); //This one
prints 0
they say...
Pass.Reference(wi);
Console.WriteLine(wi.Number) //And this one
prints 42.
}
}

class WrappedInt
{
public int Number;
}

class Pass
{
public static void Reference(WrappedInt param)
{
param.Number = 42;
}
}

--------------------------------

2. Then it goes on to say that whether it is passed by value or

reference, the original arguement is unchanged unless you use 'ref' or 'out'.
So what gives? Which is correct, 1 or 2? If 2 is correct, then the example they gave in 1 shouldn't be valid right? I may be missing something you
would find obvious.

Thanks for any explanations!


Nov 16 '05 #3

P: n/a
z_learning_tester <so*****@microsoft.com> wrote:
I'm reading the MS press C# book and there seems to be a contradiction.
Please tell me which one is correct, 1 or 2.
I would need to see *exactly* what they wrote to say for sure - it's
easy to rewrite it in your own words and end up with mistakes.
2. Then it goes on to say that whether it is passed by value or reference,
the original arguement is unchanged unless you use 'ref' or 'out'.
That's true.
So what gives? Which is correct, 1 or 2? If 2 is correct, then the example
they gave in 1 shouldn't be valid right? I may be missing something you
would find obvious.


What you're missing is that you can change a value within the object
which a variable refers to without changing the value of the variable
itself.

I've written a page trying to explain all this carefully:
http://www.pobox.com/~skeet/csharp/parameters.html

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 16 '05 #4

P: n/a
Well, I'm glad it helped. I know that it wasn't the most elegant
explanation available.
"John Smith" <so*****@microsoft.com> wrote in message
news:BZ********************@comcast.com...
OK, had to read that a *few* times.
But I've got it now.

It really took all of those examples for me to put it together- so thanks
for taking the time!

"J.Marsch" <je****@ctcdeveloper.com> wrote in message
news:eO*************@TK2MSFTNGP09.phx.gbl...
The first one does print 0, and the second does print 42. And both 1 and
2
are technically correct.

Explanation:

The key to this is understanding the difference between a reference type an
a value type.

Anything that you define as a class (like the WrappedInteger class) is a
reference type. That means that in memory, it never really "lives" inside a
variable. Rather, any variables that are of type WrappedInteger, are
"references" (think "pointer" -- not exactly like a C++ pointer, but
along those lines).

So, when you set wi = new WrappedInt();

Whats really happening is that a WrappedInt() object is being created
somewhere in memory, and then a reference (kinda like a pointer) to that
object is being stored in the variable wi.

So if you do this:
WrappedInt wi = new WrappedInt();
WrappedInt wi2 = wi;

wi2 and wi are both referencing (pointing to) the same object instance.

So,
if you do this:
wi.Number = 10;
w2.Number = 20;
Console.WriteLine(wi.Number)

You get "20", because wi and w2 are both pointing to exactly the same
location in memory.

Now, in contrast, lets look at a value type. your primitives like
ints/floats/bools (full list in the help) are value types, as is anything that you define as a struct. That means that when you assign one to the
other it is copied in memory -- it really does "live" in the variable.

So:
int x = 5;

The value 5 is deposited in the memory location for x.

int y = x;
x = 10;

y is 5, and x is a 10.

the 5 is copied from x to y, and it is now a copy -- y is independent of x so when you change x, it only affects x. This should be very familiar
ground -- its the behavior you would expect when dealing with ints in most common languages (VB 6, Delphi, etc)

Now, lets look at their example:
when they call Pass.Reference(wi), you are passing the value in wi, which is
really just a pointer to an object in memory. When the code in
reference sets Param.Number:
param.Number = 42;
It is getting the reference (pointer) location from param and runnign out into memory to access the .Number member. It is accessing the same object in memory as wi, and setting its Number property = 42, so that set

"counts"
inside of Main because you passed a reference type.

So, right now it looks like #1 was right.

Now, why is #2 right?

Well, when you call Pass.Reference(wi), you are passing the reference (the pointer in wi) to the ReferenceMethod by value. If reference tries to
modify the actual value of the pointer (by assigning it to another

object),
it will not affect the variable wi in the calling method.

Here's what I mean:
WrappedInt wi = new WrappedInt();
wi.Number = 5;
Pass.Reference(wi);
Console.WriteLine(wi.Number);
// prints "5"

public class Pass
{
public static void Reference(WrappedInt param)
{
// instead of changing .Number, lets try reassign to a new object // note the difference: I'm reassining param rather than one
// of its members
param = new WrappedInt()
param.Number = 10;
}
}

On the other hand, if you modify Referenct to accept param as a ref
parameter, and then you pass wi as a ref:
Pass.Reference(ref wi)
Console.WriteLine(wi.Number) will print a 10;

Since you passed wi by reference, the Reference method changed the

location
in memory that it was pointing to such that it is pointing to the new

object
instance. You now don't have any way to access the WrappedInt object that you originally created in main, and it will be garbage collected and

removed
from memory.
I know that was a really long, somewhat contorted explanation. I hope it helped.

"z_learning_tester" <so*****@microsoft.com> wrote in message
news:mfpAc.66015$0y.328@attbi_s03...
I'm reading the MS press C# book and there seems to be a contradiction. Please tell me which one is correct, 1 or 2.
Thanks!
Jeff

1. First it gives the code below saying that it prints 0 then 42.
They say that 42 is printed the second time since the value was wrapped in
a
class and therefore became passed by reference.
(sorry for any typos I am a newbie here ;-)

class Application
{
static void Entrance()
{
WrappedInt wi = new WrappedInt();
Console.WriteLine(wi.Number); //This one

prints
0
they say...
Pass.Reference(wi);
Console.WriteLine(wi.Number) //And this one
prints 42.
}
}

class WrappedInt
{
public int Number;
}

class Pass
{
public static void Reference(WrappedInt param)
{
param.Number = 42;
}
}

--------------------------------

2. Then it goes on to say that whether it is passed by value or

reference, the original arguement is unchanged unless you use 'ref' or 'out'.
So what gives? Which is correct, 1 or 2? If 2 is correct, then the example they gave in 1 shouldn't be valid right? I may be missing something

you would find obvious.

Thanks for any explanations!



Nov 16 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.