Problem

I was asked by a friend at work what I thought about readabilty of nullable int maths and it got me thinking. How clever should it be over readability? Can developers understand what the code is trying to achieve quickly?

If you’re new to nullable reference types or don’t use them very often then they may look confusing. To be honest I had to debug through option 1 as I wasn’t 100% what it would do. While we discussed option 1 and option 2 below it got me wondering what other ways can it be expressed and how easy is it to read.

public class NullableSumsTests
{
    public static IEnumerable<object[]> NullableAdds = new List<object[]>()
    {
        new object[] { null, null },
        new object[] { 1, 2 }
    };

    [Theory]
    [MemberData(nameof(NullableAdds))]
    public void Add(int? startingValue, int? expected)
    {
        int? index = startingValue;

        // option 1
        int? result = index + 1;

        // option 2
        int? result2 = index.HasValue ? index + 1 : null;

        // option 3
        if (index.HasValue)
        {
            index += 1;
        }

        result.Should().Be(expected);
        result2.Should().Be(expected);
        index.Should().Be(expected);
    }
}

As you can see there are many different ways to perform the same calculation and for me it comes down to readability.

  • Option 1 looks clear but if you’re unsure about nullable handling it might take a little longer to understand what it is trying to achieve.
  • Option 2 is writing out long hand what the check is and being very explicit about it and removes any ambiguity as to what it’s trying to achieve. This maybe a better way to work if you are working in a code base depending on the rest of the code base and the overall team experience levels.
  • Option 3 removes the requirement for an additional variable and continues to use the same logic and is pretty clear.

Looking at the 3 options side by side to be honest I think I prefer option 3.

Conclusion

We have taken a brief look how to handle performing a simple maths operation on a Nullable<int> or int? and how the same operation can be executed different ways depending on readability and maintainability considerations.

As with everything in development it comes down to experience, preference, readability, maintainability and consistency within the codebase as to which of the options should be used.

Let me know your thoughts and which one option you prefer. Is there another option which is “better”? Please contact me on Twitter @WestDiscGolf and let me know.