Should I use Single() or SingleOrDefault() if there is a chance that the element won't be found?

33,816

Solution 1

  • Use SingleOrDefault() if 0 or 1 items are expected
  • Use Single() if 1, not 0 or 2 and more, item is expected

Also keep in mind that there are a number of possible scenarios:

  • You got 0 when 0 or 1 was expected (ok)
  • You got 1 when 0 or 1 was expected (ok)
  • You got 2 or more when 0 or 1 was expected (error)

And:

  • You got 0 when 1 was expected (error)
  • You got 1 when 1 was expected (ok)
  • You got 2 or more when 1 was expected (error)

And don't forget about First(), FirstOrDefault() and Any()

Solution 2

I would write:

var item = list.Single(x => x.HasFoo);

If the case where this does not return a single item is so common you need a friendlier error message, then is it really an exception at all?

Solution 3

Practically, they are the same. But I prefer second one since one exception is thrown while in the first two. Exceptions are expensive.

Solution 4

I think it's OK to write

var item = list.SingleOrDefault(x => x.HasFoo);
if (item == null) ...

but you can also write

if (list.Any(x => x.HasFoo)) ...

if you don't actually need access to the value.

Solution 5

If you ALWAYS EXPECT  one element in the list, just use 

var item = list.Single(x => x.HasFoo);

and catch exception at the top level method, where you will log details of exception and show friendly message to the user.

If you sometimes expect 0 or more than 1 elements, the safest method will be

var item = list.FirstOrDefault(x => x.HasFoo);
if (item == null) 
{ 
// empty list processing, not necessary throwing exception
}

I assumed, that it is not important to verify, are more than 1 record exist or not.

Similar question was discussed in Code Project article LINQ: Single vs. SingleOrDefault

Share:
33,816
the_drow
Author by

the_drow

My name is Omer Katz and I am a very passionate software developer who specializes in ALM & SCM practices. I'm also an Agile & Lean enthusiast and practitioner. I am only 23, therefor I have only started working in the industry in 2010 but I have been programming since I was 11 and I have never stopped being passionate about it. I have a vast knowledge when it comes to planning, designing, developing & delivering software. My greatest passion is finding new ways to make the developers' lives easier and let them focus on what they know to do best, software development.

Updated on July 17, 2022

Comments

  • the_drow
    the_drow almost 2 years

    What would you prefer to see?

    try
    {
      var item = list.Single(x => x.HasFoo);
    }
    catch(InvalidOperationException e)
    {
      throw new InvalidOperationException("Exactly one item with foo expected, none found", e);
    }
    

    Or:

    var item = list.SingleOrDefault(x => x.HasFoo);
    if (item == null)
          throw new InvalidOperationException("Exactly one item with foo expected, none found");
    

    What's the best practice here? Which one makes the exception more comprehensible?