Fog Creek Software
Discussion Board




Passing by value / reference

So I come across the following gem in a C# book:

"In this example, it was a value type that was passed 'by value'. But reference types can also be passed 'by value'. As we saw previously, the immediate value held by a reference type variable is actually a memory address. So when this variable is passed 'by value', the memory address is copied to the variable specified in the method head. But of course, because the two variables will hold the same memory address, any changes made within the method body to the object located at that memory address will be reflected outside the method (although this doesn't apply for immutable reference types like strings, which act more like value types - see lesson 4)."

Right then. So passing a reference type by value actually copies the memory address of the variable, and passes that, so that any changes within the method are reflected outside the method. So explain to me again what passing by reference does?

CF
Thursday, August 26, 2004

>So explain to me again what passing by reference does?

For "Reference Types," not a whole lot.  Value types is where you get different results.

Pseudo Masochist
Thursday, August 26, 2004

It's not easy to explain. In C# (by default) and in Java parameters are passed by value. So object references are passed by value.

What the author is trying to say is that if you pass an object to a method, the method can modify the "contents" of the argument, not to what object the argument refers.

Ugh.

igor
Thursday, August 26, 2004

The Pseudo Masochist got it right.

Passing a reference type by value or by reference makes no difference as far as the programmer is concerned. If you're passing around a reference type -- either way (byval, byref), you end up with any side-effects working on the original object.

It's only when passing a value type where it makes a difference. With a value type, byval leads to a local copy and byref leads to the original object.

Sgt. Sausage
Thursday, August 26, 2004

"Passing a reference type by value or by reference makes no difference as far as the programmer is concerned."

Passing a reference type by reference means that your object itself might be pointing to an entirely different object on return, while passing by value ensures that the recipient cannot alter which object you're looking at, though they can of course alter members of the object.

Consider the following two functions, and what happens if you pass your shiny new object to each of them.

private void ObjectByValue(object passedObject)
{
  passedObject = null;
}

private void ObjectByRef(ref object passedObject)
{
  passedObject = null;
}

ObjectByValue(myShinyObject);
ObjectByRef(ref myShinyObject);

In the former case the change was to a temporary, function scope parameter that was harmlessly lost, and myShinyObject still points at your shiny object. In the latter case, your object was just made available for garbage collection (presuming you don't have other references), and myShinyObject points to null.

Dennis Forbes
Thursday, August 26, 2004

Thanks Dennis. That was exactly what I was looking for. The *object* is passed by value, but the pointer to the memory location of the contents remains the same, so the object itself can't be modified, but the contents can. Thanks!

CF
Thursday, August 26, 2004

There's also some wierdy-shit that goes on that I can't fully explain / understand when using option strict and passing inherited objects. It works when passing by value but not by reference (I think it's this way round). I thought I had the hang of it once but then something else happened that then contradicted my understanding again. doh!

gwyn
Thursday, August 26, 2004

This is a common confusion -- the problem is that people use "passed by reference" to refer to both passing the value of a reference type and passing a reference to a variable (which may itself contain a reference or a value.)

I find it helpful to give concrete examples that illustrate each.  I've written a number of blog entries on how VBScript and JScript work with both.  See

http://blogs.msdn.com/ericlippert/archive/2003/09/15/53005.aspx

for a good place to start.

Eric Lippert
Thursday, August 26, 2004

> It works when passing by value but not by reference (I think it's this way round).

In C++ it's safe to pass inherited objects by reference, but not to pass them by value: for further details, Google for the term "object slicing".

Christopher Wells
Thursday, August 26, 2004

Yeah, thanks Chris, I remember it now.. I just wish I could remember the thing that then through me off again!

gwyn
Thursday, August 26, 2004

And then you can throw C# 'out' parameters into the mix too (which behave mostly like ref, except that the parameter variable cannot be used until the function being called assigns it a value). Weeeeeee!

Joe
Thursday, August 26, 2004

==>Passing a reference type by reference means that your object itself might be pointing to an entirely different object on return, while passing by value ensures that the recipient cannot alter which object you're looking at, though they can of course alter members of the object.

Gotcha. I knew that.

That's what happens when you post before you really think about it. Duh. I'm a moron.

Sgt. Sausage
Thursday, August 26, 2004

in C++, this is a fairly common optimisation:

void whatever(class const &arg);

it is pretty much the same as passing by value, as the function cannot alter anything, but it converses call space.

Maybe the same kind of thing is useful in C#..?

i like i
Friday, August 27, 2004

C# doesn't support pass by const reference (it only supports pass by reference). In fact it doesn't support pass-by-value either (for non-value types, i.e. for any class type derived from object): if you want pass-by-value, you would have to do it explicitly by cloning the original object and then passing the clone by reference.

Christopher Wells
Friday, August 27, 2004

"In fact it doesn't support pass-by-value either"

I think you're picking at straws in a potentially confusing manner, as both Java and C# define passing by value and passing by reference to relate to the actual parameter passed, not to which the parameter is pointing.

To consider this another way, one can only pass "value" types - integers, structures, and pointers - to procedures. Given that, the by-reference and by-value refers to the value type itself - is the value type maleable or not.

Dennis Forbes
Friday, August 27, 2004

> I think you're picking at straws in a potentially confusing manner

I was trying to use those terms as they would be understood by a C++ programmer.

What I mean is that if you have a class like ...

  class Foo
  {
    ...
  }

... and a method like ...

  void Bar(Foo foo)
  {
    ...
  }

... then if you write code like ...

  Foo foo = new Foo();
  Bar(foo);

... then in C# the thing that's being passed to the Bar method is a reference or pointer to the original foo object: the C# language doesn't support passing the foo object "by value" (which, passing by value, in C++ implies creating a temporary copy of the foo object on the stack, and passing the temporary copy of the object ... which in C++ implies that the original copy of the foo object cannot be altered by the Bar method, and that the object might be subject to "object-slicing" if the Bar method doesn't take a "Foo" parameter but actually takes a paremeter whose type is a Foo superclass).

Christopher Wells
Friday, August 27, 2004

*  Recent Topics

*  Fog Creek Home