LINQ Single vs First

.NetLinq

.Net Problem Overview


LINQ:

Is it more efficient to use the Single() operator over First() when ever I know for certain that the query will return a single record?

Is there a difference?

.Net Solutions


Solution 1 - .Net

If you're expecting a Single record, it's always good to be explicit in your code.

I know others have written why you use one or the other, but I thought I'd illustrate why you should NOT use one, when you mean the other.

Note: In my code, I will typically use FirstOrDefault() and SingleOrDefault() but that's a different question.

Take, for example, a table that stores Customers in different languages using a Composite Key ( ID, Lang ):

DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).First();

This code above introduces a possible logic error ( difficult to trace ). It will return more than one record ( assuming you have the customer record in multiple languages ) but it will always return only the first one... which may work sometimes... but not others. It's unpredictable.

Since your intent is to return a Single Customer use Single();

The following would throw an exception ( which is what you want in this case ):

DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).Single();

Then, you simply hit yourself on the forehead and say to yourself... OOPS! I forgot the language field! Following is the correct version:

DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 && c.Lang == "en" ).Single();

First() is useful in the following scenario:

DBContext db = new DBContext();
NewsItem newsitem = db.NewsItems.OrderByDescending( n => n.AddedDate ).First();

It will return ONE object, and since you're using sorting, it will be the most recent record that is returned.

Using Single() when you feel it should explicitly always return 1 record will help you avoid logic errors.

Solution 2 - .Net

Single will throw an exception if it finds more than one record matching the criteria. First will always select the first record from the list. If the query returns just 1 record, you can go with First().

Both will throw an InvalidOperationException exception if the collection is empty. Alternatively you can use SingleOrDefault(). This won't throw an exception if the list is empty

Solution 3 - .Net

Single() > Returns a single specific element of a query > > When Use: If exactly 1 element is expected; not 0 or more than 1. If the list is empty or has more than one element, it will throw an Exception "Sequence contains more than one element"

SingleOrDefault() > Returns a single specific element of a query, or a default value if no result found > > When Use: When 0 or 1 elements are expected. It will throw an exception if the list has 2 or more items.

First() > Returns the first element of a query with multiple results. > > When Use: When 1 or more elements are expected and you want only the first. It will throw an exception if the list contains no elements.

FirstOrDefault() > Returns the first element of a list with any amount of elements, or a default value if the list is empty. > > When Use: When multiple elements are expected and you want only the first. Or the list is empty and you want a default value for the specified type, the same as default(MyObjectType). For example: if the list type is list<int> it will return the first number from the list or 0 if the list is empty. If it is list<string>, it will return the first string from the list or null if the list is empty.

Solution 4 - .Net

If you don't specifically want an exception thrown in the event that there is more than one item, use First().

Both are efficient, take the first item. First() is slightly more efficient because it doesn't bother checking to see if there is a second item.

The only difference is that Single() expects there to be only one item in the enumeration to begin with, and will throw an exception if there are more than one. You use .Single() if you specifically want an exception thrown in this case.

Solution 5 - .Net

There is a subtle, semantic difference between these two methods.

Use Single to retrieve the first (and only) element from a sequence that should contain one element and no more. If the sequence has more than on element your invocation of Single will cause an exception to be thrown since you indicated that there should only be one element.

Use First to retrieve the first element from a sequence that can contain any number of elements. If the sequence has more than on element your invocation of First will not cause an exception to be thrown since you indicated that you only need the first element in the sequence and do not care if more exist.

If the sequence contains no elements both method calls will cause exceptions to be thrown since both methods expect at least one element to be present.

Solution 6 - .Net

If I recall, Single() checks if there is another element after the first one (and throws an exception if it's the case), while First() stops after getting it. Both throw an exception if the sequence is empty.

Personnally, I always use First().

Solution 7 - .Net

Regarding peformance: A coworker and I were discussing the performance of Single vs First (or SingleOrDefault vs FirstOrDefault), and I was arguing for the point that First (or FirstOrDefault) would be faster and improve performance (I’m all about making our app run faster).

I’ve read several posts on Stack Overflow that debate this. Some say there are small performance gains using First instead of Single. This is because First would simply return the first item while Single must scan all the results to make sure there isn’t a duplicate (ie: if it found the item in the first row of the table, it still would scan every other row to make sure there isn’t a second value matching the condition which would then throw an error). I felt like I was on solid ground with “First” being faster than “Single” so I set out to prove it and put the debate to rest.

I setup a test in my database and added 1,000,000 rows of ID UniqueIdentifier Foreign UniqueIdentifier Info nvarchar(50) (filled with strings of numbers “0” to “999,9999”

I loaded the data and set ID as a primary key field.

Using LinqPad, my goal was to show that if you searched for a value on ‘Foreign’ or ‘Info’ using Single, that it would be much worse than using First.

I cannot explain the results I got. In almost every case, using Single or SingleOrDefault was slightly faster. This doesn’t make any logical sense to me, but I wanted to share that.

Ex: I used the following queries:

var q = TestTables.First(x=>x.Info == "314638") ;
//Vs.
Var q = TestTables.Single(x=>x.Info =="314638") ; //(this was slightly faster to my surprise)

I tried similar queries on the 'Foreign' key field which was not indexed thinking that would prove First is faster, but Single was always slightly faster in my tests.

Solution 8 - .Net

They are different. Both of them assert that the result set is not empty, but single also asserts that there is not more than 1 result. I personally use Single in cases where I only expect there to be 1 result just because getting more than 1 result back is an error and probably should be treated as such.

Solution 9 - .Net

You can try simple example to get difference. Exception will thrown on line 3;

        List<int> records = new List<int>{1,1,3,4,5,6};
        var record = records.First(x => x == 1);
        record = records.Single(x => x == 1);

Solution 10 - .Net

A lot of people I know use FirstOrDefault(), but I tend to use SingleOrDefault() more because often it would be some sort of data inconsistency if there were more than one. This is dealing with LINQ-to-Objects, though.

Solution 11 - .Net

The records in Employee entity:

Employeeid = 1: Only one employee with this ID

Firstname = Robert: More than one employee with this name

Employeeid = 10: No employee with this ID

Now it's necessary to understand what Single() and First() mean in detail.

Single()

Single() is used to return a single record which uniquely exists in a table, so the query below will return the Employee whose employeed =1 because we have only one Employee whose Employeed is 1. If we have two records for EmployeeId = 1 then it throws an error (see the error below in second query where we are using an example for Firstname.

Employee.Single(e => e.Employeeid == 1)

The above will return a single record, which has 1 employeeId

Employee.Single(e => e.Firstname == "Robert")

The above will throw an exception because multilple records are in the table for FirstName='Robert' . The exception will be

> InvalidOperationException: Sequence contains more than one element

Employee.Single(e => e.Employeeid == 10)

This will, again, throw an exception because no record exists for id=10. The exception will be

> InvalidOperationException: Sequence contains no elements.

For EmployeeId = 10 it will return null, but as we are using Single() it will throw an error. In order to handle null error we should use SingleOrDefault().

First()

First() returns from multiple records the corresponding records sorted in ascending order according to birthdate so it will return 'Robert' who is oldest.

Employee.OrderBy(e => e. Birthdate)
.First(e => e.Firstname == "Robert")

Above should return the oldest one, Robert as per DOB.

Employee.OrderBy(e => e. Birthdate)
.First(e => e.Employeeid == 10)

Above will throw an exception as no record for id =10 exists. To avoid a null exception we should use FirstOrDefault() rather than First().

Note: We can use only First()/Single() when we absolutely sure that it cannot return a null value.

In both functions use SingleOrDefault() OR FirstOrDefault() which will handle a null exception, in the case of no record found it will return null.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIan VinkView Question on Stackoverflow
Solution 1 - .NetArmstrongestView Answer on Stackoverflow
Solution 2 - .NetAlwaysAProgrammerView Answer on Stackoverflow
Solution 3 - .NetDiego MendesView Answer on Stackoverflow
Solution 4 - .NetPatrick KarcherView Answer on Stackoverflow
Solution 5 - .NetAndrew HareView Answer on Stackoverflow
Solution 6 - .NetEtienne de MartelView Answer on Stackoverflow
Solution 7 - .NetMarcus TalcottView Answer on Stackoverflow
Solution 8 - .NetjaltiereView Answer on Stackoverflow
Solution 9 - .NetChauskin RodionView Answer on Stackoverflow
Solution 10 - .NetMatt HView Answer on Stackoverflow
Solution 11 - .NetSheriffView Answer on Stackoverflow