C# keywords ref and out, differences and use.
A friend/co-worker and I were discussing ways to return/affect multiple variables and/or objects from methods and we ended up in quite the discussion and I thought I would share. We found ourselves on the topic of keywords ref and out, let’s dig into what both of those are, their differences and their limitations.
The Facts:
ref:
Passes the argument by *Reference* and not by value.
It *Must * be initialized before passing it to the method, cannot just be declared.
It does *Not* have to be modified or used in the method.
out:
Passes the argument by *Reference* and not by value.
Does *Not* have to be initialized, only needs to be declared.
The method *Must* assign a value to the out argument before the return call is hit or end of scope is reached.
The reason I point the distinction that ref and out both pass by reference and not value is because, normally we pass by value. Below is some example code to demonstrate what is going on, let’s take a look:
The code declares and initializes 2 variables, ints _x and _y to 0 respectively. Declares another int _z, and initializes it with the return from the method call to ExampleRefMethod into it where we pass int _x, and a ref to _y as arguments. Next, a console write to show the value of the returned _z and another to show the values of _x, and _y after the method call/return to see how it modified them (if it did?). Below that you can see ExampleRefMethod’s implementation, it takes two arguments and modifies them, _x to 5 and _y to 73.
Now when this is run, what do you think the outcome will be? Will our source variables be changed? Remember what is passed by value and what was passed by reference. Let’s run the code and take a look:
So what we see is, the method returned the int and initialized _z to 5, the string _s stays string and the int x stays 0 because they were passed by value so the source was not affected, only the copy passed to the method was affected. Now we didn’t get our ref returned in the conventional manner, however, because it is passed by reference and modified in the method which affects the source variable it nets us our desired result of both items being affected.
Now if we do not initialize _y to 0 and just declare it, we see that intelliSense gives us a little red squiggly under _y in the method call:
And if we try to compile / build our project, we get an compile time error:
And lastly, with a ‘ref’ I don’t have to modify it in the method and for demonstration purposes I simply removed it and let’s see the result:
Notice that _y is still 0 now instead of 73 as previously due to the fact it was not acted upon.
Ok, let’s look at ‘out’ this time and the differences. Code much simpler this time for brevity:
Ok so, we are only declaring int _y this time as unlike ref we can, passing it to our method and the console write to show the modification. Here we go:
And we see that our result is 73 as expected. Now we can instantiate _y if we want but do not have to, however we must modify it in the method. If we pass it but do not assign it in the method we get the following behavior:
We get this outcome as well if we initialize it when we declare it, it must be assigned in the method.
So that’s it, out and ref and how they are used and the differences between them, just remember the facts:
The Facts:
ref:
Passes the argument by *Reference* and not by value.
It *Must * be initialized before passing it to the method, cannot just be declared.
It does *Not* have to be modified or used in the method.
out:
Passes the argument by *Reference* and not by value.
Does *Not* have to be initialized, only needs to be declared.
The method *Must* assign a value to the out argument before the return call is hit or end of scope is reached.
Happy coding!