All 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:
predicate.InvalidOperationException is thrown with the message: "Sequence contains no elements".predicate, an InvalidOperationException 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();
predicate.predicate, returns the default value of the sequence type using default(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();
predicate.InvalidOperationException is thrown with the message "Sequence contains no elements."predicate, an InvalidOperationException 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();
predicate.predicate, returns the default value of the sequence type using default(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();
predicate, that element is returned.predicate, an InvalidOperationException is thrown with the message "Sequence contains no elements".predicate, an InvalidOperationException is thrown with the message "Sequence contains more than one element".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();
predicate, that element is returned.predicate, default(T) is returned.predicate, an InvalidOperationException is thrown with the message "Sequence contains more than one element".predicate, returns the default value of the sequence type using default(T).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();
Although you can use FirstOrDefault, LastOrDefault or SingleOrDefault to check whether a sequence contains any items, Any or Count are more reliable. This is because a return value of default(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 be default(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 use First; as Single 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, the First method, which can be satisfied after finding the first match.