I am going to try my hand at an explanation:
I think we understand how the value types work right? Value types are (int, long, struct etc.). When you send them in to a function without a ref command it COPIES the data. Anything you do to that data in the function only affects the copy, not the original. The ref command sends the ACTUAL data and any changes will affect the data outside the function.
Ok on to the confusing part, reference types:
Lets create a reference type:
List<string> someobject = new List<string>()
When you new up someobject, two parts are created:
- The block of memory that holds data for someobject.
- A reference (pointer) to that block
of data.
Now when you send in someobject into a method without ref it COPIES the reference pointer, NOT the data. So you now have this:
(outside method) reference1 => someobject
(inside method) reference2 => someobject
Two references pointing to the same object. If you modify a property on someobject using reference2 it will affect the same data pointed to by reference1.
(inside method) reference2.Add("SomeString");
(outside method) reference1[0] == "SomeString" //this is true
If you null out reference2 or point it to new data it will not affect reference1 nor the data reference1 points to.
(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true
The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject
Now what happens when you send someobject by ref to a method?
The actual reference to someobject gets sent to the method. So you now have only one reference to the data:
(outside method) reference1 => someobject;
(inside method) reference1 => someobject;
But what does this mean? It acts exactly the same as sending someobject not by ref except for two main thing:
1) When you null out the reference inside the method it will null the one outside the method.
(inside method) reference1 = null;
(outside method) reference1 == null; //true
2) You can now point the reference to a completely different data location and the reference outside the function will now point to the new data location.
(inside method) reference1 = new List<string>();
(outside method) reference1.Count == 0; //this is true