The other day, I was discussing with a colleague on whether or not the usage of out parameters is OK. If I’m honest, I immediately cringed as I am not really a fan of said keyword. But first, let’s briefly discuss what on how the ‘out’ parameter keyword works.
In C#, the ‘out’ keyword is used to allow a method to return multiple values of data. This means that the method can return data using the ‘return’ statement and modify values using the ‘out’ keyword. Why did I say modify instead of return when referring to the out statement? Simple, because what the ‘out’ does, is that it receives a pointer to said data structure and then dereferences and applies the value when a new value is assigned. This means that the ‘out’ keyword is introducing the concept of pointers.
OK, the previous paragraph may not make much sense if you do not have any experience with unmanaged languages and pointers. And that’s exactly the main problem with the ‘out’ parameter. It’s introducing pointers without the user’s awareness.
Let’s now talk about the pattern and architecture of said ‘out’ parameter. As we said earlier, the ‘out’ keyword is used in a method to allow it to return multiple values. An ‘out’ parameter gives a guarantee that the value will get initialised by the callee and the callee does not expect the value passed as the out parameter to be initialised. Let’s see an example:
User GetUser(int id, out string errorMessage) { // User is fetched from database // ErrorMessage is set if there was an error fetching the user }
This may be used as such
string errorMessage; User user = GetUser(1, out errorMessage);
By the way, C# 7 now allows the out variable to be declared inline, looking something like this:
User user = GetUser(1, out string errorMessage);
This can easily be refactored, so that the message can be returned encapsulated within the same object. It may look something like the below:
class UserWithError { User user {get; set;} string ErrorMessage {get; set;} } UserWithError GetUser(int id) { // User is fetched from database // ErrorMessage is set if there was an error fetching the user }
Let’s quickly go through the problems with the ‘out’ keyword exposed. Firstly, it’s not easy to discard the return value. With a return value, we can easily call GetUser and ignore the return value. But with the out parameter, we do have to pass a string to capture the error message, even if one does not need the actual error message. Secondly, declaration is a bit more cumbersome since it needs to happen in more than one line (since we need to declare the out parameter). Although this was fixed in C# 7, there are a lot of code-bases which are not running C# 7. Lastly, this prevents from the method to run as “async”.
By the way, ‘out’ raises a Code Quality warning, as defined by Microsoft’s design patterns.
Last thing I want to mention is the use of the ‘out’ keyword in the Try pattern, which returns a bool as a return type, and sets a value using the ‘out’ keyword. This is the only globally accepted pattern which makes use of the ‘out’ keyword.
int amount; if(Int32.TryParse(amountAsString, out amount)) { //amountAsString was indeed an integer }
Long story short, if you want a method to return multiple values, wrap them in a class; don’t use thee ‘out’ keyword.
Hear, hear.
LikeLike