DEV Community

Libin Tom Baby
Libin Tom Baby

Posted on • Edited on

FirstOrDefault vs SingleOrDefault in C# — The Complete, Practical Guide

Working with collections and LINQ is part of everyday life for a .NET developer. Yet one of the most common interview questions — and one of the most misunderstood concepts — is the difference between FirstOrDefault and SingleOrDefault.

Both methods return a single element from a sequence, but they behave very differently. Choosing the wrong one can introduce subtle bugs, performance issues, or unexpected exceptions.

This guide breaks down the differences with definitions, examples, EF Core scenarios, and when to use each method.


What FirstOrDefault Does

FirstOrDefault returns:

  • The first matching element
  • Or the default value (null for reference types) if no element exists
  • It never throws an exception for multiple matches

Example

var numbers = new List<int> { 1, 2, 3, 4 };

var result = numbers.FirstOrDefault(n => n > 2);
// result = 3
Enter fullscreen mode Exit fullscreen mode

If nothing matches

var result = numbers.FirstOrDefault(n => n > 10);
// result = 0 (default int)
Enter fullscreen mode Exit fullscreen mode

Key behavior

  • Returns first match
  • Safe when 0 or many items may exist
  • Does not enforce uniqueness

What SingleOrDefault Does

SingleOrDefault returns:

  • The only matching element
  • Or the default value if no element exists
  • But throws an exception if more than one match exists

Example

var numbers = new List<int> { 1, 2, 3 };

var result = numbers.SingleOrDefault(n => n == 2);
// result = 2
Enter fullscreen mode Exit fullscreen mode

If nothing matches

var result = numbers.SingleOrDefault(n => n == 10);
// result = 0 (default int)
Enter fullscreen mode Exit fullscreen mode

If more than one match exists

var numbers = new List<int> { 1, 2, 2, 3 };

var result = numbers.SingleOrDefault(n => n == 2);
// ❌ Throws InvalidOperationException
Enter fullscreen mode Exit fullscreen mode

Key behavior

  • Enforces uniqueness
  • Throws exception if multiple items match
  • Useful when the data model guarantees a single record

Side‑by‑Side Comparison

Feature FirstOrDefault SingleOrDefault
Returns first match ✔️
Ensures only one match exists ✔️
Throws if multiple matches ✔️
Returns default if none found ✔️ ✔️
Use when multiple matches are possible ✔️
Use when exactly one match is expected ✔️

Real‑World Scenarios

Scenario 1: Fetching a user by email (unique field)

Email is unique — there should never be two users with the same email.

var user = db.Users.SingleOrDefault(u => u.Email == email);
Enter fullscreen mode Exit fullscreen mode

If duplicates exist, you want an exception because your data is corrupted.

Use: SingleOrDefault


Scenario 2: Fetching the first active order

There may be many active orders, but you only need the first one.

var order = db.Orders
              .Where(o => o.Status == "Active")
              .FirstOrDefault();
Enter fullscreen mode Exit fullscreen mode

Use: FirstOrDefault


Scenario 3: Checking if a configuration record exists

Your system guarantees only one configuration row.

var config = db.Configurations.SingleOrDefault();
Enter fullscreen mode Exit fullscreen mode

Use: SingleOrDefault


Scenario 4: Getting the first log entry for a user

Logs are not unique — there can be many.

var log = db.Logs
            .Where(l => l.UserId == userId)
            .FirstOrDefault();
Enter fullscreen mode Exit fullscreen mode

Use: FirstOrDefault


EF Core Behavior (Important!)

FirstOrDefault in EF Core

Translates to:

SELECT TOP(1) ...
Enter fullscreen mode Exit fullscreen mode

Fast, efficient, optimized.


SingleOrDefault in EF Core

Translates to:

SELECT ...;
-- EF then checks if more than one row exists
Enter fullscreen mode Exit fullscreen mode

EF Core must read all matching rows to ensure uniqueness.

This means:

  • More database work
  • More memory
  • More time

Use it only when uniqueness is required.


Common Interview Traps

❌ “They both return one element.”

Not true — only SingleOrDefault enforces uniqueness.

❌ “Use SingleOrDefault for performance.”

Actually, FirstOrDefault is faster in most cases.

❌ “SingleOrDefault is safer.”

It’s only safer when the data must be unique.


When to Use Which (Simple Rule)

✔️ Use FirstOrDefault

When 0, 1, or many items may match

and you only need the first one.

✔️ Use SingleOrDefault

When exactly 1 item must match

and multiple matches indicate a data integrity problem.


Conclusion

Both methods look similar but serve very different purposes:

  • FirstOrDefault → flexible, safe, fast
  • SingleOrDefault → strict, enforces uniqueness, throws on duplicates

Choosing the right one improves performance, prevents hidden bugs, and makes your intent clear to anyone reading your code.

If you’re preparing for interviews or writing production-grade LINQ, understanding this difference is essential.


Updates in response to reader comments

Thanks to @nrpieper for pointing out this important EF Core behaviour

🔍 EF Core SQL Translation Detail: Why SingleOrDefault Uses TOP(2)

When you're working with LINQ-to-Objects, SingleOrDefault() simply checks the in‑memory sequence. But in Entity Framework Core, things get more interesting — and more optimized.

EF Core translates Single() and SingleOrDefault() into a SQL query that looks like this:

SELECT TOP(2) ...
Enter fullscreen mode Exit fullscreen mode

At first glance, this might seem odd. Why fetch two rows when you only want one?

Because EF Core must enforce the contract of Single*:

  • 0 rows → return default
  • 1 row → return that row
  • 2+ rows → throw an exception

Fetching two rows is the minimum needed to detect a “more than one match” violation without scanning the entire table. It’s a deliberate performance optimization.

✔️ What this means in practice

  • SingleOrDefault() is stricter and slightly heavier than FirstOrDefault()
  • EF Core will throw if more than one row matches
  • The TOP(2) pattern is expected and correct
  • This behavior is specific to EF Core’s SQL translation, not LINQ-to-Objects

✔️ Why this matters

If your intention is uniqueness enforcement, SingleOrDefault() is perfect.

If your intention is simply “give me the first match”, FirstOrDefault() is faster and avoids the extra uniqueness check.


Top comments (2)

Collapse
 
nrpieper profile image
nrpieper

SingleOrDefault, in recent EF Core versions will do a Select Top 2 ... to see if there are more than one matching row.

Collapse
 
libintombaby profile image
Libin Tom Baby

Hi @nrpieper,

Thanks so much for your valuable comment - you’re absolutely right about EF Core’s SingleOrDefault behavior and the use of SELECT TOP(2) to detect multiple matches.

I’ve updated the article to include this detail. Appreciate you taking the time to point it out!