Recently I’ve come to a realization: I use Single() and SingleOrDefault() frequently even though many developers avoid it entirely – instead always opting to use First() or FirstOrDefault(). I wanted to explain why I explicitly choose Single over First in certain situations. Under most circumstances, Single() provides a better a means of validating the intent of your LINQ, therefore helping to validate your program as a whole.
The Highlander Rule: Can there only be one?
Many developers say that they will use First() when they only expect there to be one result because it’s less risky to blow up if there are many results. Instead of throwing an annoying “sequence contains more than one element” exception, it’ll just grab the first one, right?
Doesn’t that just seem wrong to you, right off the bat? What about the other results? Do we lose confidence in the trueness of our application if we expect only one result but get many? What if the other results are completely different? Are we guaranteed that the First item is the most recent? What if it’s the oldest?
See how this decision suddenly made us question the legitimacy of our program? This should be a code smell. Something isn’t right here. We expect there to be one but we allow room for error by using First(). Many results may exist, and we’d never get notified by an exception.
If there can only be one: Use Single() or SingleOrDefault()!
Instead of looking at the “sequence contains more than one element” exception as an annoyance, let’s leverage it as a proper check and balance to our system. If we only ever expect there to be one result, then acquire that result using Single(). This way, if a mistake is made elsewhere in the program so that many results could be created, the program will encounter a fault on Single() and fail. This isn’t bad, this is a good thing! Now you know that you made a mistake somewhere in the program and you can sort it out now, rather than be surprised by it later. Suddenly, a LINQ expression with Single() becomes more than just an expression, it becomes a law that your program must adhere to.
“But what if we later decide to allow more than one result?”
If you decide to pivot away from the Highlander Rule later in the project’s lifecycle, it’s easy to do. Most likely, any surrounding code that expected a single result will now need to be updated to handle many results. You just find usages of Single() which are affected and remove them. Then, refactor the surrounding code to handle many results instead of just one.
When does it make sense to use First()?
I usually use First() only if I expect there to be many results but am positive that I only need the first one, and the rest could be ignored. This doesn’t happen very often. I might use it if I want to show the first result from a list, or as a trick to select the “top-most” result after a query. Generally speaking, I tend to favor Single(), and I treat First() as a code smell and always evaluate why First() was chosen over Single() for the situation. If the Highlander rule applies – I always refactor to Single().
How does this help development?
It helps ensure the legitimacy of the program. If we expect there to only ever be one of something, the system will break if there are more. This will hopefully notify everyone of the problem long before anyone would have discovered it with First().