Avoid out Parameters
C# has the out
parameter modifier allowing us to pass value types by reference.
First, let’s check out how arguments are passed by value without the out
keyword.
Method GetCustomerName()
takes two string
parameters:
public void GetCustomerName(string firstName, string lastName) { firstName = "Fred"; lastName = "Flintstone"; }
Let’s call GetCustomerName()
with a preset firstName
and lastName
in a unit test:
var firstName = "Barney"; var lastName = "Rubble"; GetCustomerName(firstName, lastName); firstName.Should().Be("Barney"); // PASSES! lastName.Should().Be("Rubble"); // PASSES!
The firstName
and lastName
variable content remains the same. When passing these strings by value makes a copy of the parameters inside the GetCustomerName()
. Variables firstName
and lastName
are changed inside the scope of GetCustomerName()
only yet remain “Barney” and “Rubble” outside of it.
OK, let’s use the out parameter modifier keyword:
void GetCustomerName(out string firstName, out string lastName) { firstName = "Fred"; lastName = "Flintstone"; }
Our unit test code now changes to
var firstName = "Barney"; var lastName = "Rubble"; GetCustomerName(out firstName, out lastName); firstName.Should().Be("Fred"); // PASSES! lastName.Should().Be("Flintstone"); // PASSES!
The out
keyword has changed the operation of GetCustomerName()
. Setting firstName
and lastName
to “Fred” and “Flintstone” inside GetCustomerName()
also modifies the variable outside the method because we no longer pass a copy—we are using the same variables.
So far, so good—that is how the out
parameter modifier works.
However, we should avoid creating out
parameters on our methods.
Why?
They are unexpected and unnecessary.
Method GetCustomerName()
is a query function—it requests data. The conventional way to return the data from a query function is via the return value. Returning data via the values that we passed into the method is novel and unexpected. We should try to avoid programming in ways that will confuse and make our programmer colleagues pause.
Fair enough. So, we should return the data via a return value, like this:
var name = GetCustomerName();
and GetCustomerName()
returns the data via a composite return value CustomerName
:
public class CustomerName { public string FirstName { get; } public string LastName { get; } public CustomerName(string firstName, string lastName) { FirstName = firstName; LastName = lastName; } }
public CustomerName GetCustomerName(string firstName, string lastName) { return new CustomerName("Fred", "Flintstone"); }
The FirstName
and LastName
properties can then be accessed on the return value using the property getters as shown in the string format expression below:
var name = $"{name.FirstName} {name.LastName}";
Nice—that works well.
To recap, avoid out
parameters if possible – and it is always possible. I haven’t written a method featuring an out
parameter in a decade or more. The out
parameter keyword is a programming construct that is not necessary—you’re better off returning a composite object. Just because C#, or any language, provides you with the ability to do something doesn’t mean it’s always a good idea.
Leave a Reply
Want to join the discussion?Feel free to contribute!