Why does LINQ have so many ways to return one element?
Published: Tuesday 26 December 2023
A LINQ query in C# is frequently used as a way of returning results from an enumerable type like a list.
Exploring the different ways to get one element
There are four different ways of getting a single result from a LINQ query.
MyClass class and will add three elements to a list to test this out.
public class MyRecord
{
public int Id { get; }
public MyRecord(int id)
{
Id = id;
}
}
var myRecords = new List<MyRecord>
{
new(1),
new(2),
new(3)
};
First and FirstOrDefault
Using the First method will return the first record from a LINQ query. It doesn't matter if there is more than one result, it will always return the first.
System.InvalidOperationException: 'Sequence contains no matching element'
This exception can be avoided by using the FirstOrDefault method. When it's used and there are no results, it will return NULL as the output.
var myRecords = new List<MyRecord>
{
new(1),
new(2),
new(3)
};
Console.WriteLine(myRecords.First(x => x.Id == 2).Id); // Outputs "2"
Console.WriteLine(myRecords.First(x => x.Id == 4).Id); // Throws exception
Console.WriteLine(myRecords.First().Id); // Outputs "1"
Console.WriteLine(myRecords.FirstOrDefault(x => x.Id == 4)?.Id); // Outputs ""
Single and SingleOrDefault
Using the Single method must return one record from a LINQ query. If there is more than one result, it will throw the following exception:
System.InvalidOperationException: 'Sequence contains more than one element'
And if there are no records returned, it will throw the following exception:
System.InvalidOperationException: 'Sequence contains no matching element'
To avoid the exception being thrown on no results, the SingleOrDefault method can be used. This will return NULL if there are no results. However, an exception will still be thrown if there is more than one result.
var myRecords = new List<MyRecord>
{
new(1),
new(2),
new(3)
};
Console.WriteLine(myRecords.Single(x => x.Id == 2).Id); // Outputs "2"
Console.WriteLine(myRecords.Single(x => x.Id == 4)?.Id); // Throws exception
Console.WriteLine(myRecords.Single().Id); // Throws exception
Console.WriteLine(myRecords.SingleOrDefault(x => x.Id == 4).Id); // Outputs ""
Benchmarking
We set up benchmarking for each of these methods and here are the results:
| Method | Mean | Allocated |
|---|---|---|
| First | 21.97 ns | 40 B |
| FirstOrDefault | 20.25 ns | 40 B |
| Single | 33.97 ns | 40 B |
| SingleOrDefault | 31.49 ns | 40 B |
We can see that the allocated memory for each one is the same.
FirstOrDefault and First perform faster than the Single and SingleOrDefault methods by over 10 ns. And that makes sense as the single methods need to check if there is more than one element in the query hence the additional overhead.
The differences
So the main difference is that the Single method only expects one record and will return an exception if there are more.
First method, it will return the first record from the LINQ query even if there is more than one record.
FirstOrDefault or SingleOrDefault methods are used.Latest articles
Why your EF Core queries are slow and how to fix them
Discover why your EF Core queries are slow and learn practical fixes to improve performance, reduce query times, and optimise your .NET applications.