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 valueFirstOrDefault()returns a single value or defaultTake(1)returns anIEnumerable<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->0bool->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()andFirstOrDefault()return the item itselfTake(1)returns a container that may contain one item
That is the easiest way to remember the difference:
First*-> single itemTake-> sequence
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:
numberscontains three items:10,20,30FirstOrDefault(x => x > 15)starts checking items from the beginning- It checks
1010 > 15isfalse
- It checks
2020 > 15istrue
- Because it found the first match, it stops immediately
resultbecomes20Console.WriteLine(result)prints20
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:
- Check
10-> not greater than100 - Check
20-> not greater than100 - Check
30-> not greater than100 - No match is found
- Return
default(int)which is0 - 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:
Where(x => x > 15)describes a filtered sequenceTake(1)says to keep at most one item from that filtered sequence- Enumeration begins in the
foreach 10is rejected20matches and is yieldedTake(1)has now produced one item, so it stops30is 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
nullor 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
nullis 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
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,
userisnull - accessing
user.Namecauses aNullReferenceException
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:
0may mean “no match” forint- 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:
resultis anIEnumerable<User>, not aUser
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
| Method | Returns | If no match exists | Best used when |
|---|---|---|---|
First() | T | Throws InvalidOperationException | A match must exist |
FirstOrDefault() | T | Returns default(T) | A match may not exist |
Take(1) | IEnumerable<T> | Returns empty sequence | You want up to one item as a sequence |
First() vs FirstOrDefault()
| Question | First() | FirstOrDefault() |
|---|---|---|
| Returns one item? | Yes | Yes |
| Throws when empty? | Yes | No |
Can return null for reference types? | Only if the actual item is null | Yes, when no match exists |
| Good for required data? | Yes | Usually no |
| Good for optional data? | Usually no | Yes |
FirstOrDefault() vs Take(1)
| Question | FirstOrDefault() | Take(1) |
|---|---|---|
| Result type | Single value | Sequence |
| Empty case | Default value | Empty sequence |
Easy to use in if/null checks | Yes | Not directly |
| Good for continued LINQ chaining as a sequence | Less so | Yes |
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.
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)overWhere(predicate).First(). - Prefer
FirstOrDefault(predicate)overWhere(predicate).FirstOrDefault().
Empty-sequence behavior
First()-> exceptionFirstOrDefault()->default(T)Take(1)-> emptyIEnumerable<T>
Default values
string->nullint->0bool->false- custom reference type ->
null
Watch out
FirstOrDefault()with value types can hide “no result” behind a default value like0Take(1)does not return a single objectFirst()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.
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.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Access Modifiers and static: public, private, protected, and Defaults
Learn how C# public, private, protected, and default access control visibility, and how static differs from instance members.