Are out and ref modifiers in C# a code smell?
If there's a new feature in C#, should you immediately implement it? In today's post, I discuss and offer alternatives to the out parameter.
Last week, one of my friends wanted me to do a code review for him.
During the interview process, he was given a code kata to complete for the weekend and wanted me to review his progress.
One thing I noticed in the code was a number of methods using the out
parameter modifier.
What is the out
parameter modifier?
First introduced in C# 7.0, out
parameters are used in method signatures where variables are passed by reference, but are slightly different from the ref
modifier.
So why not use the ref
modifier?
The ref
modifier requires the variable be initialized before it's passed into the method where the out
parameter modifier doesn't require initialization. It can be initialized in the receiving method and passed back.
With that said, I consider both of these to be code smells.
While I consider out
and ref
modifiers a short-term fix, they should only be used when you want something working relatively quick; to be refactored later. So it's definitely not a long term solution.
Why is it a code smell?
One of the reasons it's a code smell is because it goes "against the grain" of how a method or function is supposed to...well...function. You pass parameters into a function and it returns either a value or nothing.
In my opinion, parameters should always be passed by value and not reference. I have yet to find an instance where passing a variable by reference is better. If they are passed by reference, this makes your code more difficult to work with and refactor.
Also, FxCop and the analyzers in Visual Studio recommends not using out parameters.
What are some alternatives to using the out/ref
parameter modifier?
Similar to when I see switch statements, I start to get a twitch when I see out
or ref
modifiers.
I understand the thinking behind it. You want to return multiple return types, but you can only return one type from a method.
Let's say we are updating a name.
public bool UpdateName(out string firstName, out string lastName, out int age) { firstName = "Jonathan"; lastName = "Danylko"; age = 12; // in my mind :-p
return true; // success }
You want to update some variables and return their new value, but you also want to let the developer know whether it was successful or not.
While oversimplified, I've seen similar code to this "in the wild."
So what are the alternatives to this?
Option 1: Use a Parameter Object w/ optional Result class
One of the signs of a refactoring is the number of parameters passed into a method. My general rule of thumb is when a method's parameter count surpasses three ("and three shall be the number...no more and no less"), it's time to make a Parameter Object.
As you can see, this looks strikingly familiar to a possible person class.
So why not create a PersonParameter?
public class PersonParameter { public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } public bool Success { get; set; } }
public class Person { public void UpdateName(PersonParameter person) { person.FirstName = "Jonathan"; person.LastName = "Danylko"; person.Age = 12; // in my mind :-p
person.Success = true; } }
Since classes are passed by reference automatically, we don't need a ref
modifier on the UpdateName
method signature.
It may be a little more by adding another class for you to create and maintain, but it makes it more terse and readable in the end.
Optionally, you can move the status of the method's operation from the PersonParameter to a Result/Response object (PersonResult here).
public class PersonResult { public bool Success { get; set; } public string Message { get; set; } }
public class PersonParameter { public string FirstName { get; set; } public string LastName { get; set; } public int Age { get; set; } }
public class PersonClass { public PersonResult UpdateName(PersonParameter person) { person.FirstName = "Jonathan"; person.LastName = "Danylko"; person.Age = 12; // in my mind :-p
return new PersonResult { Success = true, Message = "We're good." }; } }
Option 2: Use Tuples
While discussed in a older post, Tuples are another option for returning multiple values.
public class PersonClass { public (string FirstName, string LastName, int Age) UpdateName(string firstName, string lastName, int age) { return (FirstName: firstName, LastName: lastName, Age: age); } }
I have to admit, though, this does look a little weird, but I would consider it a step above an out or ref modifier.
Conclusion
I presented two alternatives to using ref and out parameter modifiers while showing how they can make your code more difficult to read.
While the out/ref modifiers are common in C#, they need special consideration before you decide to use them in your code.
Do you agree? Is there a better alternative besides the two I mentioned? Do you like the ref or out modifiers? Post your comments below and let's discuss.