P
Peter Duniho
Which brings me to another question: how is passing a reference by value
not pass-by-reference?
In some sense it is. Consider, for example, the C way of doing things in
which everything is really passed by value, but you can effectively pass
something by reference by explicitly passing a reference to it. But of
course when you did that, you had to explicitly dereference the passed in
reference value. Even though C always passes things by value, you could
still essentially pass things by reference by doing it explicitly:
void SomeFunction(int *pi)
{
// The parameter is "pi"...to modify the original, you need to
// explicitly dereference "pi" using the "*" operator
*pi = 5;
}
void OtherFunction()
{
int i = 4;
SomeFunction(&i);
printf("%d\r\n", i);
}
Output:
5
Later on, we got true "passing by reference" in C++, where you simply used
the parameter identifier, but it was a reference to the original value
from the caller. This is like using the "Var" keyword in Pascal, for
example. And, of course, like using the "ref" or "out" keywords in C#.
For example:
void SomeFunction(int &i)
{
// The parameter is "i"...no extra work is necessary to modify
// the original.
i = 5;
}
void OtherFunction()
{
int i = 4;
SomeFunction(&i);
printf("%d\r\n", i);
}
Output:
5
IMHO, one very nice thing about distinguishing between passing a reference
and passing BY reference is that it makes it simpler when you are passing
a reference to a reference. In C, you have to do this by passing a
pointer to a pointer, which makes some people's head hurt. Granted, maybe
passing references by reference in C# makes some peoples head hurt too,
but I think maybe it makes fewer people's head hurt.
All that said, note that I only said "in some sense". I don't believe
it's true in the most useful sense...just in a certain way of looking at
it. In the most useful sense, passing a reference by value is definitely
*not* the same as passing by reference. That is, when you pass a
reference by value, the object to which the reference refers can be
directly modified. But the original reference that you passed in is *not*
changeable. A copy of that reference was made, and if the called function
changes the reference itself, that change will be reflected only within
the called function.
Only by passing a reference by reference can the called function modify
the original reference. And that's the difference between passing a
reference by value and passing it by reference.
For what it's worth, I still think Jon's write-up is a great place to
figure this stuff out, but since I went to the trouble of writing my own
little summary in a previous post, I am copying it here in case you find
it useful:
---- begin quoted text ----
By default passing is always "by value". The "ref" and "out" keywords
cause things to be passed "by reference". Not to be confused with the
difference between "value types" and "reference types". Again, I think
Jon's write-up does a good job of outlining the various combinations of
value and reference types being passed by value and by reference. A quick
summary though:
1) pass value type by value: a copy of the value type is made and
passed to the method
example:
void method1(int x)
{
x = 5;
}
void method2()
{
int y = 4;
method1(y);
Console.WriteLine(y);
}
output:
4
2) pass reference type by value: a copy of the reference is made and
passed to the method, but it's important to note that it's the *reference*
being copied, not the object itself. So unless the reference type is
immutable (like String, for example), the object itself can be modified by
the called method (but the reference to the object cannot be)
example:
class A
{
public int i;
public A(int j)
{
i = j;
}
}
void method1(A x)
{
x.i = 5;
x = new A(6);
}
void method2()
{
A y = new A(4);
method1(y);
Console.WriteLine(y.i);
}
output:
5
3) pass value type by reference: a reference to the value type is
passed, and the called method can modify the original value type instance
example:
void method1(ref int x)
{
x = 5;
}
void method2()
{
int y = 4;
method1(ref y);
Console.WriteLine(y);
}
output:
5
4) pass reference type by reference: a reference to the reference is
made; not only can the reference type object be modifed as in case #2, but
the reference *to* that object can be modified as well.
example:
class A
{
public int i;
public A(int j)
{
i = j;
}
}
void method1(ref A x)
{
x.i = 5;
x = new A(6);
}
void method2()
{
A y = new A(4);
method1(ref y);
Console.WriteLine(y.i);
}
output:
6
---- end quoted text ----
Pete