In order to answer your question let's first look at ValueTypes
A ValueType holds the Value. That is it does not in turn point to another memory location that holds the value but rather it's memory location is the value.
so
int i = 10;
int j = i;
What happens here is that a copy of the value of i is assigned to j. They both have the same value but they are different locations in memory. In oter words, each time you assign a valuetype to another valuetype, a copy is made.
Contract this with ReferenceTypes.
object o = 10;
object p = o;
because o is a ReferenceType o points to a memory location that holds the value of 10 (it is really boxed but I'll keep it simple). In the next line p now points to the same memory location. In other words, reference tyes have two things going.
1. An address pointer
2. The actual memory location (that address points to) that holds the actual "thing".
If you get it do far, then we can move on the passing by value and by reference.
In C# parameters are passed by value. So if you're passing a valueType to a method that expects a valuetype parameter, then
int i = 10;
SomeMethod(i);
Console.WriteLine(i);
static void SomeMethod(int value)
{
value = 20;
}
When the call is made to SomeMethod a copy of the value of i is sent to the method. If the method manipulates the parameter, it does not affect the original variable i. So what you'll see in the console window is 10;
contract this with reference types;
class Program
{
static void Main(string[] args)
{
Customer c = new Customer() { Name = "Mike" };
SomeMethod(c);
Console.WriteLine(c.Name);
}
static void SomeMethod(Customer customer)
{
customer.Name = "John";
}
}
class Customer
{
public string Name { get; set; }
}
Since c is a reference type. And C# passes parameters by value. a copy of the "value" of the reference is passed. That is the value of the Address c is pointing to is passed. In the method, since the address is the same (it's a copy but it points to the same memory location), the method is able to manipulate the state of object. So what you'll see in the console window is "John" and not "Mike".
However, if the method attempts to assign another instance to the parameter (called "customer" in this case). then things change.
class Program
{
static void Main(string[] args)
{
Customer c = new Customer() { Name = "Mike" };
SomeMethod(c);
Console.WriteLine(c.Name);
}
static void SomeMethod(Customer customer)
{
customer = new Customer();
customer.Name = "John";
}
}
class Customer
{
public string Name { get; set; }
}
Notice that in the method we create a new instance of a Customer and assign it to the parameter customer and we set the name of this new instance to "John". What we'll see in the console window is "Mike" and not john.
That is because a copy of the original variable (c) was made before passing it to the method. While now in the method we have another address and then manipulate that new address so the original instance is untouched. Make sense?
Ok, if that makes sense. then what if we actually wanted the SomeMethod to be able to do what we attempted to do? Well, then the parameter can't be passed by value but it has to be passed by reference. Meaning that the variable c and the two part (the value of address it is pointing and the address itself) are being passed. So now you're passing a reference type by reference.
class Program
{
static void Main(string[] args)
{
Customer c = new Customer() { Name = "Mike" };
SomeMethod(ref c);
Console.WriteLine(c.Name);
}
static void SomeMethod(ref Customer customer)
{
customer = new Customer();
customer.Name = "John";
}
}
class Customer
{
public string Name { get; set; }
}