If you’re tempted to write a method with a boolean return type, consider whether another design might be more appropriate. This is another in my series of posts on Code Gardening - the practice of making small improvements as you see them while you are working.
One classic illustration of the problem with boolean return values can be seen in the standard .NET framework method
int.TryParse(). Traditional use looks something like this:
This piece of code is clunky enough that one feature being considered for C# 7 is all about moving the variable declaration inline:
While this is certainly nicer - and the associated scoping rules mean that it will play nicely with other language features like LINQ - there’s a larger issue that
TryParse() really needs to return two different pieces of information: Whether the string
input could be parsed as an integer; and if it could, the value of that integer.
A better approach (if we were designing this from scratch today) would be to return an
Option<T>. If the supplied string can be successfully parsed as a string, the routine would return a
Some<int>; if not, the return would be a
None<int>. (For those wanting to search for more about this approach, this is known as the maybe monad).
In C# 6, the declaration of
TryParse() and subsequent use might look something like this:
Admittedly, this is slightly clunky because of the tight scoping of the lambda expressions.
Fortunately, pattern matching features proposed for C# 7 make this much cleaner:
The version of
int.TryParse() we have shown here returns everything you need in one value. This compares favorably with the older version where the answer to “Is this an int?” is returned directly, and the answer to “Which int is it?” is returned via a side channel.
In this example, our opening question “Are Boolean Return values Evil?” the answer is maybe … the existing design for
int.TryParse() has room for improvement, but it’s not actually a bad design.
Next time you are writing something akin to
TryParse(), have a think about the API before blindly copying what has gone before.