Question

First vs FirstOrDefault vs Take(1) in LINQ with C#

csharp.netlinq

Question

I want to understand the difference between .First(), .FirstOrDefault(), and .Take(1) in LINQ, and when each one should be used.

For example:

var result = List.Where(x => x == "foo").First();

Should .First() only be used when I want an exception if no matching item is found?

And for .FirstOrDefault():

var result = List.Where(x => x == "foo").FirstOrDefault();

Should this be used when I want the default value of the type if no result exists?

Also, how does .Take(1) compare?

var result = List.Where(x => x == "foo").Take(1);

What is the practical difference between these methods, and how do I choose the right one?

Short Answer

By the end of this page, you will understand how First(), FirstOrDefault(), and Take(1) behave in LINQ, especially when a sequence may be empty. You will learn when each method is appropriate, what values they return, when they throw exceptions, and which option is most readable in real C# code.

Concept

LINQ methods often answer slightly different questions, even when they look similar.

First() asks:

  • Give me the first item
  • Throw an exception if there is none

FirstOrDefault() asks:

  • Give me the first item
  • If there is none, return the default value for the type instead

Take(1) asks:

  • Give me a sequence containing up to one item
  • If there is no item, return an empty sequence

That difference matters because these methods return different kinds of results:

  • First() returns a single value
  • FirstOrDefault() returns a single value or default
  • Take(1) returns an IEnumerable<T> sequence

Why this matters

In real programs, sometimes not finding a result is a bug. Other times, it is normal.

Use First() when:

  • you expect at least one matching item
  • no result means something is wrong
  • you want failure to be explicit

Use FirstOrDefault() when:

  • no result is a valid possibility
  • you want to handle the missing case yourself
  • returning null, 0, false, or another default is acceptable

Use Take(1) when:

  • you still want a sequence, not a single item
  • you plan to continue chaining sequence-based LINQ operations
  • the code should represent “up to one result” as a collection

Important detail about default

The default value depends on the type:

  • reference types like string -> null
  • int -> 0
  • bool -> false
  • structs -> a zeroed/default struct value

That means FirstOrDefault() can sometimes blur the line between:

  • “no item found”
  • “an item was found and its value happens to equal the default”

For example, with List<int>, FirstOrDefault() returning 0 does not automatically tell you whether:

  • the sequence was empty, or
  • the first matching item was actually 0

This is one reason developers often choose carefully between these methods.

Mental Model

Think of a row of boxes on a shelf.

  • First() means: Open the first box. If there is no box, that is an error.
  • FirstOrDefault() means: Open the first box. If there is no box, hand me an empty placeholder instead.
  • Take(1) means: Give me a tray that can hold one box. If a box exists, put it on the tray. If not, give me an empty tray.

So:

  • First() and FirstOrDefault() return the item itself
  • Take(1) returns a container that may contain one item

That is the easiest way to remember the difference:

  • First* -> single item
  • Take -> sequence
Take Quiz

Syntax and Examples

The most common forms are:

var item = source.First();
var item = source.FirstOrDefault();
var sequence = source.Take(1);

You can also pass a predicate directly instead of calling Where(...) first:

var item = source.First(x => x == "foo");
var item = source.FirstOrDefault(x => x == "foo");

This is usually cleaner than:

var item = source.Where(x => x == "foo").First();
var item = source.Where(x => x == "foo").FirstOrDefault();

Example 1: First()

var names = new List<string> { "bar", "foo", "baz" };
var result = names.First(x => x == "foo");
Console.WriteLine(result);

Output:

foo

If no matching item exists, this throws an InvalidOperationException.

Example 2: FirstOrDefault()

var names = new List<string> { "bar", "baz" };
var result = names.FirstOrDefault(x => x == "foo");
Console.WriteLine(result == null ? "null" : result);

Output:

null

Because string is a reference type, the default value is null.

Example 3: Take(1)

var names = new List<string> { "bar", "foo", "baz" };
var result = names.Where(x => x == "foo").Take(1);

foreach (var item in result)
{
    Console.WriteLine(item);
}

Output:

foo

If there is no match, the loop simply prints nothing.

Example 4: value types with FirstOrDefault()

var numbers = new List<int> { 1, 2, 3 };
var result = numbers.FirstOrDefault(x => x > 10);
Console.WriteLine(result);

Output:

0

That 0 is the default value of int, not a found item.

Step by Step Execution

Consider this example:

var numbers = new List<int> { 10, 20, 30 };
var result = numbers.FirstOrDefault(x => x > 15);
Console.WriteLine(result);

Here is what happens step by step:

  1. numbers contains three items: 10, 20, 30
  2. FirstOrDefault(x => x > 15) starts checking items from the beginning
  3. It checks 10
    • 10 > 15 is false
  4. It checks 20
    • 20 > 15 is true
  5. Because it found the first match, it stops immediately
  6. result becomes 20
  7. Console.WriteLine(result) prints 20

Output:

20

Now compare with no match:

var numbers = new List<int> { 10, 20, 30 };
var result = numbers.FirstOrDefault(x => x > 100);
Console.WriteLine(result);

Step by step:

  1. Check 10 -> not greater than 100
  2. Check 20 -> not greater than 100
  3. Check 30 -> not greater than 100
  4. No match is found
  5. Return default(int) which is 0
  6. Print 0

Now compare Take(1):

var numbers = new List<int> { 10, 20, 30 };
var result = numbers.Where(x => x > 15).Take(1);

foreach (var n in result)
{
    Console.WriteLine(n);
}

What happens:

  1. Where(x => x > 15) describes a filtered sequence
  2. Take(1) says to keep at most one item from that filtered sequence
  3. Enumeration begins in the foreach
  4. 10 is rejected
  5. 20 matches and is yielded
  6. Take(1) has now produced one item, so it stops
  7. 30 is never needed

This shows that Take(1) is still efficient, but its result is a sequence, not a single value.

Real World Use Cases

Use First() when missing data is unexpected

var adminUser = users.First(u => u.Role == "Admin");

Good when:

  • your business rules guarantee at least one admin
  • no admin means the system is in an invalid state

Use FirstOrDefault() when missing data is normal

var middleName = names.FirstOrDefault(n => n.Type == "Middle");

Good when:

  • the item may or may not exist
  • you want to check for null or another default afterward

Use Take(1) when an API expects a sequence

var firstError = logEntries.Where(e => e.Level == "Error").Take(1);

Good when:

  • you want to pass the result to another method that accepts IEnumerable<T>
  • you want to keep working with sequence operations

Database queries with Entity Framework

var customer = db.Customers.FirstOrDefault(c => c.Email == email);

Common because:

  • the customer may not exist
  • null is easy to handle in application logic

Processing files or logs

var firstWarning = lines.FirstOrDefault(line => line.Contains("WARNING"));

Useful when:

  • you only need the earliest match
  • no warning line is not necessarily an error
Take Quiz

Real Codebase Usage

In real C# projects, developers usually choose based on intent.

Common pattern: fail fast with First()

var config = configs.First(c => c.Key == "ConnectionString");

This communicates:

  • this value must exist
  • if it does not, the application should fail rather than continue incorrectly

Common pattern: optional lookup with FirstOrDefault()

var existingUser = users.FirstOrDefault(u => u.Email == email);
if (existingUser == null)
{
    return NotFound();
}

This is a very common web API pattern.

Guard clauses after FirstOrDefault()

var order = orders.FirstOrDefault(o => o.Id == id);
if (order == null)
{
    throw new ArgumentException("Order not found.");
}

This lets you control the error message instead of relying on LINQ's default exception.

Prefer predicate overloads for readability

Instead of:

var user = users.Where(u => u.IsActive).FirstOrDefault();

Prefer:

var user = users.FirstOrDefault(u => u.IsActive);

It is shorter and expresses the intent directly.

Take(1) in pipelines

var previewItems = products
    .Where(p => p.InStock)
    .OrderBy(p => p.Name)
    .Take(1);

This is useful when the next code still expects a sequence, such as:

  • passing to a serializer
  • combining with other sequences
  • returning IEnumerable<T> from a method

A related note: Single() and SingleOrDefault()

In real codebases, developers often use these when they expect exactly one match, not just the first one. That is stricter than First() and can catch duplicate data issues.

Common Mistakes

Mistake 1: Using First() when no match is possible

Broken example:

var user = users.First(u => u.Email == inputEmail);
Console.WriteLine(user.Name);

Problem:

  • if no user matches, this throws InvalidOperationException

Better:

var user = users.FirstOrDefault(u => u.Email == inputEmail);
if (user != null)
{
    Console.WriteLine(user.Name);
}

Mistake 2: Forgetting that FirstOrDefault() may return null

Broken example:

var user = users.FirstOrDefault(u => u.Email == inputEmail);
Console.WriteLine(user.Name);

Problem:

  • if no user is found, user is null
  • accessing user.Name causes a NullReferenceException

Better:

var user = users.FirstOrDefault(u => u.Email == inputEmail);
if (user == null)
{
    Console.WriteLine("User not found");
}
else
{
    Console.WriteLine(user.Name);
}

Mistake 3: Misreading default values for value types

Broken assumption:

var result = numbers.FirstOrDefault(x => x > 100);
if (result == 0)
{
    Console.WriteLine("Found zero");
}

Problem:

  • 0 may mean “no match” for int
  • or it may be a real matching value in other scenarios

Avoid this by:

  • using .Any() first when needed
  • or choosing a nullable type

Example:

var hasMatch = numbers.Any(x => x > 100);
var result = numbers.FirstOrDefault(x => x > 100);

Mistake 4: Thinking Take(1) returns a single item

Broken example:

var result = users.Where(u => u.IsActive).Take(1);
Console.WriteLine(result.Name);

Problem:

  • result is an IEnumerable<User>, not a User

Better:

var result = users.Where(u => u.IsActive).Take(1);
foreach (var user in result)
{
    Console.WriteLine(user.Name);
}

Mistake 5: Writing Where(...).FirstOrDefault() unnecessarily

Less clear:

var user = users.Where(u => u.IsActive).FirstOrDefault();

Clearer:

var user = users.FirstOrDefault(u => u.IsActive);

Both work, but the second is usually easier to read.

Comparisons

MethodReturnsIf no match existsBest used when
First()TThrows InvalidOperationExceptionA match must exist
FirstOrDefault()TReturns default(T)A match may not exist
Take(1)IEnumerable<T>Returns empty sequenceYou want up to one item as a sequence

First() vs FirstOrDefault()

QuestionFirst()FirstOrDefault()
Returns one item?YesYes
Throws when empty?YesNo
Can return null for reference types?Only if the actual item is nullYes, when no match exists
Good for required data?YesUsually no
Good for optional data?Usually noYes

FirstOrDefault() vs Take(1)

QuestionFirstOrDefault()Take(1)
Result typeSingle valueSequence
Empty caseDefault valueEmpty sequence
Easy to use in if/null checksYesNot directly
Good for continued LINQ chaining as a sequenceLess soYes

A small style improvement

These are equivalent in intent:

var result = list.Where(x => x == "foo").FirstOrDefault();
var result = list.FirstOrDefault(x => x == "foo");

The second form is generally preferred because it is more direct.

Take Quiz

Cheat Sheet

// Throws if no match
var item = source.First(x => condition);

// Returns default(T) if no match
var item = source.FirstOrDefault(x => condition);

// Returns sequence with 0 or 1 items
var items = source.Where(x => condition).Take(1);

Quick rules

  • Use First() when a result must exist.
  • Use FirstOrDefault() when a result may not exist.
  • Use Take(1) when you need a sequence, not a single item.
  • Prefer First(predicate) over Where(predicate).First().
  • Prefer FirstOrDefault(predicate) over Where(predicate).FirstOrDefault().

Empty-sequence behavior

  • First() -> exception
  • FirstOrDefault() -> default(T)
  • Take(1) -> empty IEnumerable<T>

Default values

  • string -> null
  • int -> 0
  • bool -> false
  • custom reference type -> null

Watch out

  • FirstOrDefault() with value types can hide “no result” behind a default value like 0
  • Take(1) does not return a single object
  • First() does not mean “the only one”; it just means “the first one found”

FAQ

When should I use First() instead of FirstOrDefault() in LINQ?

Use First() when your logic expects a matching item to always exist, and the absence of one should be treated as an error.

What does FirstOrDefault() return if nothing is found?

It returns default(T). For reference types like string, that is usually null. For value types like int, it is 0.

Is Take(1) the same as FirstOrDefault()?

No. FirstOrDefault() returns a single value. Take(1) returns a sequence that contains zero or one item.

Does First() return the only matching item?

No. It returns the first matching item it encounters. There may be more matches after that.

Should I use Where(...).FirstOrDefault() or FirstOrDefault(...)?

Usually FirstOrDefault(...) is clearer and shorter. Both are valid, but the predicate overload is preferred for readability.

What exception does First() throw on an empty sequence?

It throws InvalidOperationException.

How can I tell whether FirstOrDefault() returned a real value or a default value?

For reference types, check for null. For value types, it can be harder. You may need Any(), a nullable type, or different logic.

When is Take(1) a better choice?

When the next part of your code expects an IEnumerable<T> and you want to keep the result as a sequence.

Take Quiz

Mini Project

Description

Build a small employee lookup tool that demonstrates the difference between required results, optional results, and sequence-based results. This is useful because real applications often need to fetch one record, handle missing records safely, or return a small subset of data as a collection.

Goal

Create a console app that searches employees using First(), FirstOrDefault(), and Take(1), and shows how each behaves when matches exist or do not exist.

Requirements

  • Create a list of employees with at least three entries.
  • Use First() to find a required employee and handle the exception if not found.
  • Use FirstOrDefault() to search for an optional employee and print a safe message if missing.
  • Use Take(1) to return up to one matching employee as a sequence.
  • Print clear output showing the difference between the three approaches.
Take Quiz

Keep learning

Related questions

View more