How it works
First and Single are not interchangeable ways to retrieve an element. First returns the earliest matching element in the source's order. Single asserts that exactly one element matches. In the sample there are two even numbers, so First returns two while Single rejects the ambiguous selection.
The final query asks for a value greater than five. Only seven qualifies, so Single succeeds. That successful call states a stronger contract than First would: a later change adding another qualifying value should be detected instead of silently selecting whichever appears first.
Neither operator invents a result when no element matches. Their OrDefault alternatives allow the missing case, but still need careful interpretation because a type's default can be a valid domain value. SingleOrDefault also continues to reject multiple matches; it relaxes the missing case, not the uniqueness requirement.
A common application mistake is using First to conceal duplicate identifiers in imported data. If an identifier must be unique, choosing the first duplicate can produce inconsistent behavior when input order changes. Validate uniqueness at the appropriate boundary and report a meaningful diagnostic rather than accepting an arbitrary representative.
Practice with three arrays: no qualifying values, one qualifying value, and two qualifying values. Record which queries return, which produce a default, and which throw. Include zero in a separate experiment to show why the default integer result alone cannot always distinguish a missing record from a real record.
Finally, give a repository-like lookup method an explicit cardinality contract. It might return a nullable record for a missing identifier and reject duplicates as corrupted input. Callers should not need to reverse-engineer the choice from an incidental LINQ operator hidden several functions away. Tests should name the missing, unique, and ambiguous cases separately.
A working example
using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
int[] values = { 2, 4, 7 };
Console.WriteLine(values.First(value => value % 2 == 0));
try { Console.WriteLine(values.Single(value => value % 2 == 0)); }
catch (InvalidOperationException) { Console.WriteLine("ambiguous"); }
Console.WriteLine(values.Single(value => value > 5));
Expected output
2 ambiguous 7
Use Single only when exactly one matching element is a real invariant.