One thing I run into a lot when reviewing C# code that uses LINQ is that we developers tend to gravitate towards using First() rather than Single(), even though that’s almost never what we actually want.
Both operate on a collection and return one element from it. Both throw if no element is found. If you don’t want to throw when no element is found, both can be called as SingleOrDefault() or FirstOrDefault() which returns a default value instead of throwing when no element is found.
But the two methods behave very differently in one simple regard: Single() throws if more than one item is matched, and First() doesn’t.
Consider the following just-work-with-me-here-I-know-it-would-have-other-problems-in-the-real-world-example, where you’re trying to reset the password of a user with a given email address.
var user = usersQueryable.First(user => user.EmailAddress == “[email protected]”);
user.ResetPassword();
If you’ve got two users with the same email address, you’ve got a problem. You just reset the first one’s email address, but who was first? Was it the person you intended? Maybe, maybe not. You have no way of knowing.
“Well, that’s terrific, Derek, but if we really could have multiple people with the same email address, I wouldn’t be looking up by it, so that’s a stupid example. Our email addresses have a unique constraint in the database, so this code would work just fine for me!”
Well, that’s true. It will work just fine. But if what you just described is the case, that’s exactly why you should be using Single()… it makes that assumption explicit in your code! You’re advertising to everyone that you do not expect there to ever be more than one matching user. If the back-end ever changes out from under you, such as now allowing users to have multiple accounts tied to the same email address, it will almost always be best if your code starts throwing exceptions due to its now-incorrect assumption rather than performing operations on what is perhaps the wrong user. Exceptions are easy to debug, are more likely to get spotted by system or unit tests, and give you the feedback that something is wrong very quickly. Users complaining that their password sometimes randomly seems to get reset is less easy to debug, less likely to be caught by automated testing, and may go unnoticed for quite a while.
There are cases when First() is appropriate, such as when you want the first item in a list but don’t particularly care what it is (such as automatically selecting the first item of a drop-down list when a user first hits a page), but in the majority of the cases I see in the projects I’ve worked on where there is some kind of predicate passed in, Single() is really what we want.
Make sure you know which you want, and use the one that matches your expectations.