First FirstOrDefault Last LastOrDefault Single and SingleOrDefault
suggest changeAll six methods return a single value of the sequence type, and can be called with or without a predicate.
Depending on the number of elements that match the predicate
or, if no predicate
is supplied, the number of elements in the source sequence, they behave as follows:
First()
- Returns the first element of a sequence, or the first element matching the provided
predicate
. - If the sequence contains no elements, an
InvalidOperationException
is thrown with the message: “Sequence contains no elements”. - If the sequence contains no elements matching the provided
predicate
, anInvalidOperationException
is thrown with the message “Sequence contains no matching element”.
Example
// Returns "a":
new[] { "a" }.First();
// Returns "a":
new[] { "a", "b" }.First();
// Returns "b":
new[] { "a", "b" }.First(x => x.Equals("b"));
// Returns "ba":
new[] { "ba", "be" }.First(x => x.Contains("b"));
// Throws InvalidOperationException:
new[] { "ca", "ce" }.First(x => x.Contains("b"));
// Throws InvalidOperationException:
new string[0].First();
FirstOrDefault()
- Returns the first element of a sequence, or the first element matching the provided
predicate
. - If the sequence contains no elements, or no elements matching the provided
predicate
, returns the default value of the sequence type usingdefault(T)
.
Example
// Returns "a":
new[] { "a" }.FirstOrDefault();
// Returns "a":
new[] { "a", "b" }.FirstOrDefault();
// Returns "b":
new[] { "a", "b" }.FirstOrDefault(x => x.Equals("b"));
// Returns "ba":
new[] { "ba", "be" }.FirstOrDefault(x => x.Contains("b"));
// Returns null:
new[] { "ca", "ce" }.FirstOrDefault(x => x.Contains("b"));
// Returns null:
new string[0].FirstOrDefault();
Last()
- Returns the last element of a sequence, or the last element matching the provided
predicate
. - If the sequence contains no elements, an
InvalidOperationException
is thrown with the message “Sequence contains no elements.” - If the sequence contains no elements matching the provided
predicate
, anInvalidOperationException
is thrown with the message “Sequence contains no matching element”.
Example
// Returns "a":
new[] { "a" }.Last();
// Returns "b":
new[] { "a", "b" }.Last();
// Returns "a":
new[] { "a", "b" }.Last(x => x.Equals("a"));
// Returns "be":
new[] { "ba", "be" }.Last(x => x.Contains("b"));
// Throws InvalidOperationException:
new[] { "ca", "ce" }.Last(x => x.Contains("b"));
// Throws InvalidOperationException:
new string[0].Last();
LastOrDefault()
- Returns the last element of a sequence, or the last element matching the provided
predicate
. - If the sequence contains no elements, or no elements matching the provided
predicate
, returns the default value of the sequence type usingdefault(T)
.
Example
// Returns "a":
new[] { "a" }.LastOrDefault();
// Returns "b":
new[] { "a", "b" }.LastOrDefault();
// Returns "a":
new[] { "a", "b" }.LastOrDefault(x => x.Equals("a"));
// Returns "be":
new[] { "ba", "be" }.LastOrDefault(x => x.Contains("b"));
// Returns null:
new[] { "ca", "ce" }.LastOrDefault(x => x.Contains("b"));
// Returns null:
new string[0].LastOrDefault();
Single()
- If the sequence contains exactly one element, or exactly one element matching the provided
predicate
, that element is returned. - If the sequence contains no elements, or no elements matching the provided
predicate
, anInvalidOperationException
is thrown with the message “Sequence contains no elements”. - If the sequence contains more than one element, or more than one element matching the provided
predicate
, anInvalidOperationException
is thrown with the message “Sequence contains more than one element”. - Note: in order to evaluate whether the sequence contains exactly one element, at most two elements has to be enumerated.
Example
// Returns "a":
new[] { "a" }.Single();
// Throws InvalidOperationException because sequence contains more than one element:
new[] { "a", "b" }.Single();
// Returns "b":
new[] { "a", "b" }.Single(x => x.Equals("b"));
// Throws InvalidOperationException:
new[] { "a", "b" }.Single(x => x.Equals("c"));
// Throws InvalidOperationException:
new string[0].Single();
// Throws InvalidOperationException because sequence contains more than one element:
new[] { "a", "a" }.Single();
SingleOrDefault()
- If the sequence contains exactly one element, or exactly one element matching the provided
predicate
, that element is returned. - If the sequence contains no elements, or no elements matching the provided
predicate
,default(T)
is returned. - If the sequence contains more than one element, or more than one element matching the provided
predicate
, anInvalidOperationException
is thrown with the message “Sequence contains more than one element”. - If the sequence contains no elements matching the provided
predicate
, returns the default value of the sequence type usingdefault(T)
. - Note: in order to evaluate whether the sequence contains exactly one element, at most two elements has to be enumerated.
Example
// Returns "a":
new[] { "a" }.SingleOrDefault();
// returns "a"
new[] { "a", "b" }.SingleOrDefault(x => x == "a");
// Returns null:
new[] { "a", "b" }.SingleOrDefault(x => x == "c");
// Throws InvalidOperationException:
new[] { "a", "a" }.SingleOrDefault(x => x == "a");
// Throws InvalidOperationException:
new[] { "a", "b" }.SingleOrDefault();
// Returns null:
new string[0].SingleOrDefault();
Recommendations
- Although you can use
FirstOrDefault
,LastOrDefault
orSingleOrDefault
to check whether a sequence contains any items,Any
orCount
are more reliable. This is because a return value ofdefault(T)
from one of these three methods doesn’t prove that the sequence is empty, as the value of the first / last / single element of the sequence could equally bedefault(T)
- Decide on which methods fits your code’s purpose the most. For instance, use
Single
only if you must ensure that there is a single item in the collection matching your predicate — otherwise useFirst
; asSingle
throw an exception if the sequence has more than one matching element. This of course applies to the “*OrDefault”-counterparts as well. - Regarding efficiency: Although it’s often appropriate to ensure that there is only one item (
Single
) or, either only one or zero (SingleOrDefault
) items, returned by a query, both of these methods require more, and often the entirety, of the collection to be examined to ensure there in no second match to the query. This is unlike the behavior of, for example, theFirst
method, which can be satisfied after finding the first match.
Found a mistake? Have a question or improvement idea?
Let me know.
Table Of Contents