Introduction
LINQ has element operators that return a single or a specified element from a collection. The element operators are Single, SingleOrDefault, First, FirstOrDefault, Last, and LastOrDefault.
Single
If an element match is detected, it returns a single element from the collection. If there are no or several matches for that element in the collection, an exception is thrown.
SingleOrDefault
If an element match is detected, it returns a single element from the collection. If there are multiple matches for that element in the collection, an exception is issued. If there is no match for that element in the collection, the default value is returned.
First
If one or more matches are found for an element, it returns the first specified element from the collection. If no matching element is discovered in the collection, an exception is issued.
FirstOrDefault
If one or more matches are found for an element, it returns the first specified element from the collection. If there is no match for that element in the collection, the default value is returned.
As an illustration
List<int> Data = new List<int> { 10, 20, 30, 40, 50, 80 };
//Aim to obtain the element at the given location
Console.WriteLine("Data.ElementAt(1), {0}", Data.ElementAt(1)); //result: 20
Console.WriteLine();
//Try to obtain the element at the given location if it exists; if not, return the default value
Console.WriteLine("Data.ElementAtOrDefault(10), {0}", Data.ElementAtOrDefault(10)); //result: 0, since default value is 0
Console.WriteLine();
Console.WriteLine("Data.First(), {0}", Data.First()); //result: 10
Console.WriteLine("Data.Last(), {0}", Data.Last()); //result: 80
Console.WriteLine();
//Aim for the first element in the collection of matching elements.
Console.WriteLine("Data.First(x => x <= 20), {0}", Data.First(x => x <= 20)); //result: 10
Console.WriteLine();
//If the first element is not found in the collection of matched elements, the default value is returned.
Console.WriteLine("Data.SingleOrDefault(x => x >= 900), {0}", Data.SingleOrDefault(x => x >= 900)); //result: 0, since default value is 0
Console.WriteLine();
Console.WriteLine("Data.SingleOrDefault(x => x > 50), {0}", Data.SingleOrDefault(x => x > 50)); //result: 80
Console.WriteLine();
//Aim for a solitary element
// Data = new List<int> { 10, 20, 30, 40, 50, 80, 10 };
// Data.Single(x => x == 10); //Exception: Sequence contains more than one element
//If there is just one element, try to obtain it; if not, return the default value.
// Data = new List<int> { 10, 20, 30, 40, 50, 80, 10 };
// Data.SingleOrDefault(x => x == 10); //Exception: Sequence contains more than one element
//If element 10 exists, attempt to obtain it.
Console.WriteLine("Data.Single(x => x == 10), {0}", Data.Single(x => x == 10)); //result: 10
Console.WriteLine();
//If there is just one element, try to obtain it; if not, return the default value.
Console.WriteLine("Data.SingleOrDefault(x => x == 90), {0}", Data.SingleOrDefault(x => x == 90)); //result: 0, since default value is 0
Console.WriteLine();
Output
//Aim for a solitary element
Data = new List<int> { 10, 20, 30, 40, 50, 80, 10 };
Data.Single(x => x == 10); //Exception: Sequence contains more than one element
//If there is just one element, try to obtain it; if not, return the default value.
Data = new List<int> { 10, 20, 30, 40, 50, 80, 10 };
Data.SingleOrDefault(x => x == 10); //Exception: Sequence contains more than one element
Console.WriteLine("Data.SingleOrDefault(x => x > 50), {0}", Data.SingleOrDefault(x => x >= 50));
When to utilize First, FirstOrDefault, Single, and SingleOrDefault?
The following considerations should be made when selecting Single, SingleOrDefault, First, and FirstOrDefault:
- Use Single or SingleOrDefault if you want an exception to be thrown in the event that the result set has more records than necessary.
- Use SingleOrDefault if you want a default value to be returned in the event that there are no records in the result set.
- Use First or FirstOrDefault when you always want one record, regardless of what else is in the result set.
- Use FirstOrDefault if you want a default value to be used in the event that the result set is empty.
Performance between SingleOrDefault and FirstOrDefault
FirstOrDefault is usually faster than SingleOrDefault since it iterates through the collection until it finds the first match. While SingleOrDefault iterates through the entire collection to find a single match.
We learned the new technique and evolved together.
Happy coding! 😊