Have you ever wondered what's the difference between .Single and .First methods in C#? At the first glance, they both do the same. They return one element from the list... However, there are differences in the behavior of each.
Single
The Single method returns one element from a collection, based on a predicate. It looks through the entire list and looks for the desired element.
var users = new List<User>
{
new() {FirstName = "George", LastName = "Doe", Age = 18},
new() {FirstName = "Jane", LastName = "Doe", Age = 21},
new() {FirstName = "Jay", LastName = "Doe", Age = 23},
new() {FirstName = "John", LastName = "Doe", Age = 36},
new() {FirstName = "Michael", LastName = "Doe", Age = 45},
};
var result = users.Single(x => x.FirstName == "George");
However, there's are two four things to remember:
- .Single goes through the entire list, even if the first element matches the predicate right away. There's a reason for that, which is the fact that...
- .Single throws an exception when there is more than one element matching the predicate. So, if there would be two users with the same first name in the list, the .Single method would throw an InvalidOperationException.
- .Single throws the same exception when there's no element matching the predicate.
- .Single also throws the InvalidOperationException when the source collection is empty.
What if the same example Single would be called without any predicate? You guessed it right - the InvalidOperationException would be thrown. That's because there is more than 1 element matching the predicate.
First
The First method without any parameter returns the first element from the collection.
var users = new List<User>
{
new() {FirstName = "George", LastName = "Doe", Age = 18},
new() {FirstName = "Jane", LastName = "Doe", Age = 21},
new() {FirstName = "Jay", LastName = "Doe", Age = 23},
new() {FirstName = "John", LastName = "Doe", Age = 36},
new() {FirstName = "Michael", LastName = "Doe", Age = 45},
};
var result = users.First(x => x.FirstName == "George");
That's the first difference compared to the Single method (it would throw an exception if there was more than 1 element).
- The First method similarly to the Single method can return an element from the collection based on a predicate. The difference is the fact that it returns the first element from the collection matching the predicate. It doesn't iterate through the entire collection to check for duplicates.
- Similar to the Single method, the First method throws an InvalidOperationException when there's no element satisfying the condition in the predicate or when the sequence is empty.
The key difference to remember - the .First method doesn't throw an exception when there's more than one element matching the condition in the predicate. Also, the .First method without the predicate will return first element from the sequence (even though there might be more than 1 element).
What if I told you there are few more options?
Find
You might want to just element from the collection and don't worry about exceptions if it doesn't exist - the .Find method would be the right choice!
var users = new List<User>
{
new() {FirstName = "George", LastName = "Doe", Age = 18},
new() {FirstName = "Jane", LastName = "Doe", Age = 21},
new() {FirstName = "Jay", LastName = "Doe", Age = 23},
new() {FirstName = "John", LastName = "Doe", Age = 36},
new() {FirstName = "Michael", LastName = "Doe", Age = 45},
};
var result = users.Find(x => x.FirstName == "xxx"); // returns null
Single or... default
You might want to search for an element and make sure that it's only one within the collection and not worry about an exception when it's not found - the .SingleOrDefault method would be the right choice! (note: it returns null when it doesn't find the element specified by criteria)
var users = new List<User>
{
new() {FirstName = "George", LastName = "Doe", Age = 18},
new() {FirstName = "Jane", LastName = "Doe", Age = 21},
new() {FirstName = "Jay", LastName = "Doe", Age = 23},
new() {FirstName = "John", LastName = "Doe", Age = 36},
new() {FirstName = "Michael", LastName = "Doe", Age = 45},
};
var result = users.SingleOrDefault(x => x.FirstName == "xxx"); // returns null
var someoneWithDoeLastName = users.SingleOrDefault(x => x.LastName == "Doe"); // throws an exception
First or... default
You might want to get the first element matching the criteria and not worry about an exception when it's not found - the .FirstOrDefault method would be the right choice (note: it return null when it doesn't find the element specified by criteria)
var users = new List<User>
{
new() {FirstName = "George", LastName = "Doe", Age = 18},
new() {FirstName = "Jane", LastName = "Doe", Age = 21},
new() {FirstName = "Jay", LastName = "Doe", Age = 23},
new() {FirstName = "John", LastName = "Doe", Age = 36},
new() {FirstName = "Michael", LastName = "Doe", Age = 45},
};
var result = users.FirstOrDefault(x => x.FirstName == "xxx"); // returns null
var someoneWithDoeLastName = users.FirstOrDefault(x => x.LastName == "Doe"); // returns first item from the list, in this example it would be George Doe, Age 18
Which one do you use the most?
PS. Get a Free Ebook with more LINQ examples at https://dotnetcoreschool.com
Top comments (0)