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.

Written by Jonathan "JD" Danylko • Last Updated: • Develop •

Picture of a skunk

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.

ASP.NET 8 Best Practices on Amazon

ASP.NET 8 Best Practices by Jonathan Danylko


Reviewed as a "comprehensive guide" and a "roadmap to excellence" with over 120 Best Practices for ASP.NET Core 8, Jonathan's first book by Packt Publishing explores proven techniques for every phase of the SDLC.

Learn industry-standard concepts to improve your coding, debugging, and deployment of ASP.NET Core websites.

Order now on Amazon.com button

Picture of Jonathan "JD" Danylko

Jonathan "JD" Danylko is an author, web architect, and entrepreneur who's been programming for over 30 years. He's developed websites for small, medium, and Fortune 500 companies since 1996.

He currently works at Insight Enterprises as an Architect.

When asked what he likes to do in his spare time, he replies, "I like to write and I like to code. I also like to write about code."

comments powered by Disqus