251

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?

NoWar
  • 36,338
  • 80
  • 323
  • 498
Ian Vink
  • 66,960
  • 104
  • 341
  • 555

11 Answers11

353

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.

Community
  • 1
  • 1
Armstrongest
  • 15,181
  • 13
  • 67
  • 106
  • 91
    Both the Single and First methods can take an expression parameter for filtering, so the Where function is not necessary. Example: Customer customer = db.Customers.Single( c=> c.ID == 5 ); – Josh Noe Feb 05 '13 at 06:42
  • 6
    @JoshNoe - I'm curious, is there a difference between `customers.Where(predicate).Single()` `customers.Single(predicate)`? – drzaus Jun 11 '13 at 18:10
  • 9
    @drzaus - Logically, no, they both filter the values to be returned based on the predicate. However, I checked out the disassembly, and Where(predicate).Single() has three extra instructions in the simple case I made. So, while I'm no IL expert, but it appears that customers.Single(predicate) should be more efficient. – Josh Noe Jun 11 '13 at 19:06
  • 6
    @JoshNoe it is quite an opposite as it turns out. – AgentFire Mar 04 '14 at 13:01
  • 11
    @AgentFire [To back up your statement](http://stackoverflow.com/questions/21194750/which-is-faster-singlepredicate-or-wherepredicate-single) – M. Mimpen Oct 30 '14 at 14:39
  • `NewsItem newsitem = db.NewsItems.OrderByDescending( n => n.AddedDate ).Single();` will also return the most recent record. – Jogi Jul 03 '16 at 11:16
  • Should not, because it throws an error if there are more than one record in your collection. At least according to Armstrongest text. – swe Jul 04 '16 at 13:51
  • @RehanKhan Have you tested that with datasets with more than one record? It should fail. – Armstrongest Nov 04 '16 at 19:36
  • 2
    @JoshNoe Thanks Josh. I am tempted to edit the answer to remove the `Where` clause, but figure leaving it in there adds some clarity, especially for someone starting out who is wondering about the difference between `Single()` and `First()` – Armstrongest Nov 04 '16 at 19:39
  • 1
    http://www.technicaloverload.com/linq-single-vs-singleordefault-vs-first-vs-firstordefault/ – Mahesh Malpani May 25 '18 at 03:34
  • However great an answer this is, it is only answering the sub-question, and not the main question... I agree that the community should recommend good practices, but I do not agree that answers that don't fully answer the questions should be chosen as correct. There is no mention of the performance here, and some people may come here to learn about the details of C# or LINQ, and not just the best practices. – Chexxor Mar 06 '19 at 09:40
  • @M.Mimpen [But this](https://stackoverflow.com/questions/21194750/which-is-faster-singlepredicate-or-wherepredicate-single#comment89321362_21194850) is to [contradict yours](https://stackoverflow.com/questions/2724096/linq-single-vs-first#comment41914320_2724246): "_Now (2018) I test this again and i get other results. In my test the .single(..) was faster as .where(..).single(). But just by a factor below 10%_" I'd suggest it's [an Atwood moment](https://blog.codinghorror.com/the-sad-tragedy-of-micro-optimization-theater/). – ruffin Oct 31 '22 at 15:39
  • Is there value in this combination? `db.NewsItems.OrderByDescending( n => n.AddedDate ).First().Single()` – Dan Ciborowski - MSFT Apr 17 '23 at 00:39
86

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

Jenish Rabadiya
  • 6,708
  • 6
  • 33
  • 62
AlwaysAProgrammer
  • 2,927
  • 2
  • 31
  • 40
  • 5
    "If the query returns just 1 record, you can go with First()" Why not use Single() to better communicate your intent? Also, if we somehow magically did get multiple items when we were expecting exactly one, wouldn't we want to know about that? Otherwise our program is running in a potentially corrupted state. – user2051770 Sep 24 '20 at 15:53
42

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.

Community
  • 1
  • 1
Diego Mendes
  • 10,631
  • 2
  • 32
  • 36
  • 2
    Nice explanation. I'd only change that you can use `First` when *1 or more elements are expected*, not only "more than 1", and `FirstOrDefault` with any amount of elements. – Andrew Aug 11 '16 at 21:09
20

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.

Armstrongest
  • 15,181
  • 13
  • 67
  • 106
Patrick Karcher
  • 22,995
  • 5
  • 52
  • 66
18

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.

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
15

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().

Etienne de Martel
  • 34,692
  • 8
  • 91
  • 111
15

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.

Marcus Talcott
  • 321
  • 2
  • 4
  • 3
    If it's on an indexed field than the database doesn't need to do a scan to ensure it's unique. It already knows that it is. So there's no overhead there, and the only overhead on the server side is ensuring only one record came back. Doing performance tests myself it's not conclusive one way or another – mirhagk Dec 04 '15 at 23:00
  • 1
    I don't think these results would be the same on a complex object if you were searching on a field not used by IComparer. – Anthony Nichols Jan 13 '17 at 22:19
  • That should be an another question. Make sure to include source of your *test*. – Sinatr Nov 08 '17 at 10:03
  • If it's in-memory, there can be performance differences due to caching. In case you test `First` first and `Single` next, everything may already be in cache and therefore takes less time to compute. In case of a query that is translated to SQL, note that the `First` will translate to a `SELECT TOP 1` and `Single` will translate to `SELECT TOP 2`, to verify only one was found. This can have subtle differences with how the query planner decides on the query plan, and with complicated queries I've seen it happen that one will take seconds and the other one will take forever. – Dave Van den Eynde Jan 17 '23 at 12:59
5

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);
Chauskin Rodion
  • 1,204
  • 1
  • 11
  • 13
5

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.

jaltiere
  • 1,068
  • 6
  • 11
3

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.

Matt H
  • 7,311
  • 5
  • 45
  • 54
-1

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.

Cindy Meister
  • 25,071
  • 21
  • 34
  • 43
Sheriff
  • 738
  • 10
  • 20