LINQ: How to retrieve a single item in C# the smart way

LINQ has totally changed the way we code in C#, offering a powerful and expressive syntax for querying and manipulating data. In this post, we’re going to explore some LINQ methods that return a single object—great for when you need just one specific item from a collection and want to keep your code clean and readable.

Base code for the examples

To make things easier, let’s use a simple class called Product:

				
					public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

				
			

Now let’s set up a list of products that will serve as our sample data:

				
					List<Product> products = new List<Product>
{
    new Product { Id = 1, Name = "Laptop", Price = 1200 },
    new Product { Id = 2, Name = "Tablet", Price = 400 },
    new Product { Id = 3, Name = "Smartphone", Price = 800 },
    new Product { Id = 4, Name = "Monitor", Price = 300 },
    new Product { Id = 5, Name = "Keyboard", Price = 50 }
};

				
			

Now, let’s explore the LINQ methods we can use to retrieve a single item from this collection according to different criteria.

First

The First method returns the first element in a sequence. You can use it with or without a condition:

				
					Product firstItem = products.First();
Product firstMatchingItem = products.First(p => p.Price < 500);

				
			

In the first example, firstItem will be the “Laptop”, which is the first item in the list. In the second example, firstMatchingItem will be the “Tablet”, which is the first product with a price lower than 500.

Even though “Monitor” and “Keyboard” also match the condition, First returns the first match and stops searching.

Just keep in mind — if there’s no match or the list is empty, First will throw an InvalidOperationException. So, it’s a good idea to handle that with a try-catch block:

				
					try
{
    Product expensiveProduct = products.First(p => p.Price > 2000);
}
catch (InvalidOperationException ex)
{
    Console.WriteLine("No matching item found: " + ex.Message);
}

				
			

FirstOrDefault

If you want to avoid exceptions when no item is found, FirstOrDefault is a safer alternative:

				
					Product matchingItem = products.FirstOrDefault(p => p.Price > 2000);

				
			

In this case, matchingItem will be null, because there’s no product with a price higher than 2000.

Starting in .NET 6, you can provide a default value directly in the method:

				
					Product matchingItem = products.FirstOrDefault(
    p => p.Price > 2000,
    new Product { Id = 0, Name = "Product not found", Price = 0 });

				
			

So now, if no product matches the condition, matchingItem will contain a default product instead of null.

Single

Single is similar to First, but with stricter behavior. It returns the only element that matches a condition — if there’s none or more than one match, it throws an exception.

				
					Product productWithId1 = products.Single(p => p.Id == 1);
Product uniqueProduct = products.Single(p => p.Price > 500);

				
			

In the first case, productWithId1 is the “Laptop”. But in the second case, since both “Laptop” and “Smartphone” have prices over 500, an exception is thrown because Single expects only one matching element.

SingleOrDefault

This one works like Single, but returns null if no match is found (instead of throwing an exception):

				
					Product matchingItem = products.SingleOrDefault(p => p.Price > 2000);

				
			

You can also provide a default value if you want:

				
					Product matchingItem = products.SingleOrDefault(
    p => p.Price > 2000,
    new Product { Id = 0, Name = "Product not found", Price = 0 });

				
			

Last

Last is like First, but it returns the last element that matches a condition:

				
					Product lastMatchingItem = products.Last(p => p.Price > 500);

				
			

In this example, lastMatchingItem will be the “Smartphone”, which is the last product in the list with a price over 500.

If nothing matches, Last also throws an exception — so it’s good practice to handle it with care.

LastOrDefault

Finally, there’s LastOrDefault, which returns null if there’s no match:

				
					Product lastMatchingItem = products.LastOrDefault(p => p.Price > 2000);

				
			

Again, you can provide a fallback value like this:

				
					Product lastMatchingItem = products.LastOrDefault(
    p => p.Price > 2000,
    new Product { Id = 0, Name = "Product not found", Price = 0 });

				
			

Wrapping Up

LINQ’s single-result methods are powerful tools that make your code cleaner and more expressive. Whether you use First, FirstOrDefault, Single, SingleOrDefault, Last, or LastOrDefault, knowing how and when to use each one can help you avoid bugs, handle exceptions properly, and write much more readable code.