What's the difference between the 'ref' and 'out' keywords?
ref
tells the compiler that the object is initialized before entering the function, while out
tells the compiler that the object will be initialized inside the function.
So while ref
is two-ways, out
is out-only.
The ref
modifier means that:
- The value is already set and
- The method can read and modify it.
The out
modifier means that:
- The Value isn't set and can't be read by the method until it is set.
- The method must set it before returning.
Let's say Dom shows up at Peter's cubicle about the memo about the TPS reports.
If Dom were a ref argument, he would have a printed copy of the memo.
If Dom were an out argument, he'd make Peter print a new copy of the memo for him to take with him.
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
ref is in and out.
You should use out
in preference wherever it suffices for your requirements.