There are two concepts here.
- Reference types vs. value types
- Passing by value vs. passing by reference
Let's tackle the second one first.
Passing something by value means that you give the method its own copy of that value, and it's free to change that value however it wants to, without those changes leaking back into the code that called the method.
For instance, this:
Int32 x = 10;
SomeMethod(x); // pass by value
There's no way x is going to be anything other than 10 after the call returns in this case, since whatever SomeMethod did to its copy of the value, it only did to its own value.
However, passing by reference means that we don't really give the method its own value to play with, rather we give it the location in memory where our own value is located, and thus anything that method does to the value will be reflected back to our code, because in reality, there's only one value in play.
So this:
Int32 x = 10;
SomeMethod(ref x); // pass by reference
In this case, x might hold a different value after SomeMethod returns than it did before it was called.
So that's passing by value vs. passing by reference.
And now to muddle the waters. There's another concept, reference types vs. value types, which many confuses. Your question alludes to you being confused about the issue as well, my apologies if you're not.
A reference type is actually a two-part thing. It's a reference, and it's whatever the reference refers to. Think of a house you know the address of. You writing the address on a piece of paper does not actually put the entire house on that paper, rather you have a "reference" to that particular house on your piece of paper.
A reference type in .NET is the same thing. Somewhere in memory there is an object, which is a set of values, grouped together. The address of this object you store in a variable. This variable is declared to be a type which is a reference type, which allows this two-part deal.
The nice thing about reference types is that you might have many references to the same actual object, so even if you copy the reference around, you still only have one object in memory.
Edit: In respect to the question, an array is a reference type. This means that your variable only holds the address of the actual array, and that array object is located somewhere else in memory.
A value type, however, is one thing, the entire value is part of the "value type", and when you make copies of that, you make distinct copies
Here's an example of value types:
struct SomeType
{
public Int32 Value;
}
SomeType x = new SomeType;
x.Value = 10;
SomeType y = x; // value type, so y is now a copy of x
y.Value = 20; // x.Value is still 10
However, with a reference type, you're not making a copy of the object it refers to, only the reference to it. Think of it like copying the address of that house onto a second piece of paper. You still only have one house.
So, by simply changing the type of SomeType to be a reference type (changing struct
to class
):
class SomeType
{
public Int32 Value;
}
SomeType x = new SomeType;
x.Value = 10;
SomeType y = x; // reference type, so y now refers to the same object x refers to
y.Value = 20; // now x.Value is also 20, since x and y refer to the same object
And now for the final thing; passing a reference type by value.
Take this method:
public void Test(SomeType t)
{
t.Value = 25;
}
Given our class-version of SomeType above, what we have here is a method that takes a reference type parameter, but it takes it as being passed by value.
What that means is that Test cannot change t
to refer to another object altogether, and make that change leak back into the calling code. Think of this as calling a friend, and giving him the address you have on your piece of paper. No matter what your friend is doing to that house, the address you have on your paper won't change.
But, that method is free to modify the contents of the object being referred to. In that house/friend scenario, your friend is free to go and visit that house, and rearrange the furniture. Since there is only one house in play, if you go to that house after he has rearranged it, you'll see his changes.
If you change the method to pass the reference type by reference, not only is that method free to rearrange the contents of the object being referred to, but the method is also free to replace the object with an altogether new object, and have that change reflect back into the calling code. Basically, your friend can tell you back "From now on, use this new address I'll read to you instead of the old one, and forget the old one altogether".