LINQ Fundamentals - Single() Vs SingleOrDefault() - Part Two

In first part we discussed First() and FirstOrDefault() extension method, In this part we will discuss Single() and SingleOrDefault().

This is the continuation of previous article, following is the link:

In the first part we discussed First() and FirstOrDefault() extension method. In this part we will discuss Single() and SingleOrDefault().

I am taking Employee class which we have used in the previous article.

Following is the Employee class:

  1. class Employee  
  2.     {  
  3.         public int Id {get; set;}  
  4.         public string Name {get; set;}  
  5.     }  

Following is the array of Employee,  and it returns IEnumerable of Employee i.e. IEnumerable<Employee>. Here is the hardcoded data, but you can get the data from the database.

  1. public static IEnumerable<Employee> GetAllEmp()  
  2.         {  
  3.             IEnumerable<Employee> developers = new Employee []  
  4.            {  
  5.               new Employee {Id=101, Name="Ashutosh"},  
  6.               new Employee {Id=102, Name="Nilesh"},  
  7.               new Employee {Id=103, Name="Amar"},  
  8.               new Employee {Id=104, Name="Ashutosh"},  
  9.               new Employee {Id=105, Name="Ashutosh"}  
  10.            };  
  11.             return developers;  
  12.         }  

Single()

It returns the only element from a sequence. It means when we query in the collection on any given criteria or filter the record from the collection then Single Extension method expects that the sequence should have the only element. We can see a little difference between Single() and First(), if a sequence has more than one element then First() returns the first element from that sequence, but Single() must expect the only element from a sequence, not more than one.

  1. var emp = Employee.GetAllEmp()  
  2. .Where(x=> x.Name == "Nilesh").Single();             
  3. Console.WriteLine($"Id:{emp.Id},Name:{emp.Name}");  

As we can see in the above LINQ query, we filtered employee record by employee name and we know there is only one employee which matches the filtered criteria.

LINQ

In the above case we did positive testing, now we need to do negative testing.

There are two test cases for negative testing:

  1. When filtered criteria returns more than one element in a sequence.
  2. When filtered criteria do not return any record.

First Test Case

We can take an employee name whose occurrence is more than one time in the collection, so “Ashutosh” has more than one occurrence in the above-given employee array.

LINQ

We can see in the above code snippet, Single() throws an exception that states that “Sequence contains more than one element”, so Single() expects only one element in a sequence unlike First().

Second Test Case

We can take an invalid employee name, let’s suppose Rahul.

LINQ

Single() also throws an exception, Single() can’t handle null value, Single() and First() both behave the same way in this case.

SingleOrDefault()

SingleOrDefault() works the same as Single() does, SingleOrDefault() returns the only element from a sequence, but here is an advantage over Single(), so if there is no record in the collection which matches input criteria then SingleOrDefault() can handle null values and it does not throw an exception. SingleOrDefault() throws an exception when a sequence contains more than one element, in this case, it behaves the same way as Single().

Conclusion

Use Single() when you are sure that the query must return only one record, and use SingleOrDefault() when a query returns the only element from the sequence, or a default value if the sequence is empty.