var vs Explicit Types in C#: When Should You Use Each?
There is a surprisingly heated debate in C# development:
Should you use
varor explicitly declare the type?
Some developers write this:
var customer = new Customer();
Others prefer:
Customer customer = new Customer();
And then there are developers who use var everywhere:
var name = "John";
var age = 35;
var isActive = true;
So which approach is actually better?
The answer is: neither is universally better.
var and explicit types are both useful. The important question is not:
“Which one should I always use?”
It is:
“Which one makes this code easier to understand and maintain?”
In this article, we'll look at the practical differences between var and explicit types in modern C#, including when each approach improves readability—and when var can make your code harder to understand.
What Is var in C#?
Let's start with the most important misconception.
When you write:
var customer = new Customer();
C# is not creating a dynamically typed variable.
The compiler determines the type at compile time.
In this example:
var customer = new Customer();
the compiler knows that:
customer → Customer
It is essentially the same as:
Customer customer = new Customer();
The difference is that you are asking the compiler to infer the type rather than writing it explicitly.
var is statically typed
Consider:
var age = 30;
The compiler infers:
age → int
You cannot later do this:
age = "thirty";
The compiler will reject it.
This is completely different from dynamic:
dynamic age = 30;
age = "thirty";
dynamic allows the variable's runtime type to change.
var does not.
var vs Explicit Types
Here is the basic comparison:
var | Explicit Type |
|---|---|
| Type inferred by compiler | Type written by developer |
| Statically typed | Statically typed |
| Must be initialized | Can be declared before initialization |
| Reduces repetitive code | Makes type immediately visible |
| Excellent with obvious types | Excellent when type communicates intent |
| Common with LINQ | Useful for APIs and abstractions |
For example:
var customer = new Customer();
versus:
Customer customer = new Customer();
Both produce a variable of type Customer.
There is no runtime performance difference simply because you used var.
Does var Affect Performance?
This is one of the most common questions.
The short answer is:
No.
Consider:
var customer = new Customer();
and:
Customer customer = new Customer();
The compiler knows the type in both cases.
var does not mean:
Figure out the type at runtime
Instead, it means:
Compiler, infer the type for me.
So don't choose between var and explicit types based on performance.
Choose based on readability and maintainability.
When var Makes Your Code Better
There are several situations where var can make C# code significantly cleaner.
1. When the Type Is Obvious
Consider:
Customer customer = new Customer();
The type appears twice.
You already know that new Customer() creates a Customer.
Using var removes unnecessary repetition:
var customer = new Customer();
This is one of the strongest use cases for var.
The right-hand side tells you exactly what the type is.
Another example
Instead of:
List<Customer> customers = new List<Customer>();
you can write:
var customers = new List<Customer>();
The second version is shorter without hiding useful information.
2. var Works Especially Well With LINQ
LINQ is another area where var can make code much easier to read.
Consider:
var activeCustomers = customers
.Where(c => c.IsActive)
.OrderBy(c => c.Name)
.ToList();
You could explicitly write:
List<Customer> activeCustomers = customers
.Where(c => c.IsActive)
.OrderBy(c => c.Name)
.ToList();
But the type isn't particularly interesting here.
The important part is what the code is doing:
customers
↓
Where
↓
OrderBy
↓
ToList
↓
activeCustomers
var keeps the focus on the operation.
3. Anonymous Types Require var
There are situations where var isn't just convenient—it is necessary.
For example:
var result = new
{
Name = "John",
Age = 35
};
The compiler creates an anonymous type.
You don't have a named type like:
CustomerSummary
to declare explicitly.
Therefore:
var result = new
{
Name = "John",
Age = 35
};
is the natural way to work with anonymous types.
This is particularly common in LINQ projections:
var result = customers.Select(c => new
{
c.Id,
c.Name,
c.Email
});
Trying to replace var with an explicit type isn't practical because the compiler-generated anonymous type has no convenient source-level name.
4. Complex Generic Types
Imagine working with a complicated generic type:
Dictionary<int, List<Customer>> customersByRegion =
new Dictionary<int, List<Customer>>();
This is perfectly valid, but repetitive.
With var:
var customersByRegion =
new Dictionary<int, List<Customer>>();
The code becomes easier to scan.
This becomes even more useful when generic types become deeply nested.
For example:
var results = new Dictionary<
string,
List<(int Id, string Name)>>();
Writing the complete type twice would add noise without adding much meaning.
When Explicit Types Are Better
Now we get to the important part.
Using var everywhere is not necessarily good coding.
Sometimes the type itself communicates important information.
In those situations, an explicit type can make the code much easier to understand.
5. When the Right-Hand Side Hides the Type
Consider:
var result = GetData();
What is result?
You need to navigate to GetData() or inspect its definition to find out.
Maybe it returns:
Customer
Maybe:
List<Customer>
Maybe:
CustomerResponse
Maybe:
IEnumerable<Customer>
The variable declaration doesn't tell you.
Compare that with:
CustomerResponse result = GetData();
Now the type is immediately visible.
This is a situation where an explicit type can improve readability.
6. When the Abstraction Is Important
This is one of my favorite reasons to use explicit types.
Consider:
var customerRepository = new SqlCustomerRepository();
The variable is now explicitly tied to:
SqlCustomerRepository
But perhaps your application should depend on an abstraction:
ICustomerRepository customerRepository =
new SqlCustomerRepository();
This tells the reader something important:
The application uses the
ICustomerRepositoryabstraction, while the actual implementation happens to beSqlCustomerRepository.
That information is valuable.
Using:
var customerRepository =
new SqlCustomerRepository();
can hide that design decision.
7. Dependency Injection Is a Good Example
Consider a service:
public class OrderService
{
private readonly IOrderRepository _repository;
public OrderService(IOrderRepository repository)
{
_repository = repository;
}
}
Here the explicit interface is meaningful.
It communicates that the service depends on:
IOrderRepository
not a specific implementation.
That's valuable architectural information.
You wouldn't want to replace the field with something like:
private readonly var _repository;
because var cannot be used for fields.
And that's actually useful—the type of a field is often part of the design contract.
8. var Cannot Be Used Everywhere
Another important point:
var is primarily for local variables.
This is valid:
public void Process()
{
var customer = new Customer();
}
But this is invalid:
private var customer;
Fields require an explicit type:
private Customer customer;
Similarly, method parameters require explicit types:
public void ProcessCustomer(Customer customer)
{
}
You cannot write:
public void ProcessCustomer(var customer)
{
}
So var is not a replacement for explicit typing throughout your application.
9. Be Careful With Numeric Types
Sometimes var can hide an important distinction.
Consider:
var value = 100;
The compiler infers:
int
But perhaps the business logic expects:
long
or:
decimal
Writing:
decimal price = 100;
communicates something important about the value.
For example:
decimal orderTotal = 1499.99m;
is arguably clearer than:
var orderTotal = 1499.99m;
The latter is still correct, but the explicit type tells the reader that this value represents a decimal quantity.
In financial code, type information can be part of the meaning.
10. Explicit Types Can Communicate Intent
Consider:
var timeout = 30;
What is 30?
Seconds?
Minutes?
Milliseconds?
Perhaps:
int timeout = 30;
doesn't solve that either.
But an explicit type can sometimes help:
TimeSpan timeout = TimeSpan.FromSeconds(30);
Now the code communicates the intent much better.
This leads to a broader principle:
Choose the declaration that communicates the most useful information with the least unnecessary noise.
Sometimes that is var.
Sometimes it is an explicit type.
var Does Not Mean “Less Type Safety”
A common misconception is:
"Explicit types are safer than
var."
Not really.
Both are statically typed.
For example:
var customer = new Customer();
The compiler knows:
customer is Customer
Therefore this won't compile:
customer = 10;
The same is true for:
Customer customer = new Customer();
Both are type-safe.
The difference is primarily where the type is written.
A Practical Rule I Use
Instead of following a rigid rule like:
Always use
var.
or:
Never use
var.
Use this rule:
Use
varwhen the type is obvious from the right-hand side. Use an explicit type when the type itself adds useful information.
For example:
Good use of var
var customer = new Customer();
The type is obvious.
Good use of var
var customers = new List<Customer>();
Again, the type is obvious.
Good use of var
var activeCustomers = customers
.Where(c => c.IsActive)
.ToList();
The exact implementation type is usually not important at the declaration site.
Good use of explicit type
ICustomerRepository repository =
new SqlCustomerRepository();
The abstraction is meaningful.
Good use of explicit type
decimal total = CalculateOrderTotal();
The type communicates important domain information.
What About var With Interfaces?
Here's an interesting example.
Suppose:
IEnumerable<Customer> customers =
GetCustomers();
You could write:
var customers = GetCustomers();
Which one is better?
It depends on what GetCustomers() returns.
Suppose the method signature is:
public IEnumerable<Customer> GetCustomers()
{
...
}
Then:
var customers = GetCustomers();
will infer:
IEnumerable<Customer>
In this situation, var is perfectly reasonable.
But if the method returns a concrete implementation:
public List<Customer> GetCustomers()
{
...
}
then:
var customers = GetCustomers();
makes the variable a:
List<Customer>
Whereas:
IEnumerable<Customer> customers = GetCustomers();
intentionally exposes only the abstraction.
That's a subtle but important difference.
var and Refactoring
One of the biggest advantages of var becomes apparent during refactoring.
Suppose you start with:
var customers = GetCustomers();
and later change the return type of GetCustomers() from:
List<Customer>
to:
IReadOnlyList<Customer>
The local variable declaration doesn't need to change.
With an explicit type:
List<Customer> customers = GetCustomers();
you may need to update the declaration as well.
However, this isn't an argument for using var everywhere.
Refactoring should preserve the intended abstraction.
If the code deliberately requires:
IEnumerable<Customer>
then explicitly declaring that abstraction can be the better choice.
A Common Mistake: Using var to Hide Bad Naming
Sometimes developers use var because the type is difficult to understand.
For example:
var x = GetSomething();
This doesn't make the code cleaner.
It makes it harder to understand.
The problem might actually be the variable name.
Compare:
var x = GetSomething();
with:
var activeCustomers = GetActiveCustomers();
The second version communicates intent through the name.
Good code doesn't rely entirely on types.
It communicates through:
meaningful names
clear methods
appropriate abstractions
understandable types
var vs Explicit Types in ASP.NET Core
This becomes particularly interesting in ASP.NET Core applications.
Consider:
var customer = await _customerService
.GetCustomerAsync(id);
If the method name clearly communicates what it returns, var is easy to understand.
But consider:
var response = await _service.ExecuteAsync(request);
Now the type may not be obvious.
Maybe it's:
CustomerResponse
Maybe:
ApiResponse<Customer>
Maybe:
ServiceResult<Customer>
In this situation, writing:
CustomerResponse response =
await _service.ExecuteAsync(request);
can make the code easier to maintain.
The more important the type is to understanding the code, the stronger the argument for writing it explicitly.
What About var in foreach?
var works particularly well with foreach.
Instead of:
foreach (Customer customer in customers)
{
Console.WriteLine(customer.Name);
}
you can write:
foreach (var customer in customers)
{
Console.WriteLine(customer.Name);
}
Here the type is generally obvious from the collection.
Both are readable.
I personally wouldn't consider either version inherently wrong.
Choose the style that is consistent with the surrounding codebase.
var and Modern C#
Modern C# has increasingly embraced type inference.
You'll frequently see:
var service = new CustomerService();
var customers = new List<Customer>();
var result = customers
.Where(x => x.IsActive)
.ToList();
This isn't because C# is becoming dynamically typed.
It is because modern C# tries to reduce unnecessary repetition while retaining static type safety.
The goal is not:
Write fewer characters.
The goal is:
Make the code easier to read.
Those are not always the same thing.
A Simple Decision Framework
When you're unsure whether to use var, ask yourself three questions.
Question 1: Is the type obvious?
If yes:
var customer = new Customer();
var is a good choice.
If no:
CustomerResponse response = GetResponse();
An explicit type may be better.
Question 2: Does the type communicate important information?
If yes, consider writing it explicitly.
For example:
IOrderRepository repository =
new SqlOrderRepository();
The interface communicates an architectural boundary.
Question 3: Does var make the code easier or harder to understand?
This is ultimately the most important question.
Compare:
var customers = new List<Customer>();
with:
List<Customer> customers = new List<Customer>();
The first is cleaner.
Now compare:
var result = Execute();
with:
OrderProcessingResult result = Execute();
The second may be clearer.
What I Would Avoid
I wouldn't recommend rules like:
"Always use var"
Too extreme.
It can hide useful type information.
"Never use var"
Also too extreme.
It creates unnecessary repetition and makes LINQ and generic code noisier.
"Use var only for primitive types"
Not a useful rule either.
var is often more useful for complex types.
"Use explicit types because they're faster"
Incorrect.
var doesn't inherently make code slower or faster.
A Practical Style Guide
Here's a simple style guide you can apply to most C# projects.
| Situation | Recommendation |
|---|---|
new Customer() | var |
new List<Customer>() | var |
| Complex generic construction | var |
| LINQ queries | Usually var |
| Anonymous types | var |
| Type is unclear from method call | Explicit type |
| Interface abstraction matters | Explicit type |
| Domain meaning is important | Often explicit |
| Fields/properties | Explicit type |
| Method parameters | Explicit type |
| Return types | Explicit type |
For example:
var customer = new Customer();
var customers = new List<Customer>();
var activeCustomers = customers
.Where(c => c.IsActive)
.ToList();
IOrderRepository repository =
new SqlOrderRepository();
decimal orderTotal =
CalculateOrderTotal();
This gives you a good balance between brevity and clarity.
The Bigger Lesson
The var vs explicit type debate is actually part of a much bigger software engineering principle.
Code is communication.
You're not writing code only for the compiler.
You're writing it for:
your future self
your teammates
code reviewers
maintainers
developers debugging production issues
The compiler already knows the type.
The question is:
Does the human reader need to see it?
If the answer is no, var can reduce noise.
If the answer is yes, write the type explicitly.
That's a much better rule than blindly following a team preference.
Final Recommendation
Don't treat var and explicit types as competing programming philosophies.
They're simply two tools for expressing the same statically typed C# code.
Use:
var customer = new Customer();
when the type is already obvious.
Use:
CustomerResponse response = GetResponse();
when seeing the type helps the reader.
Use:
IOrderRepository repository =
new SqlOrderRepository();
when the abstraction itself communicates an important design decision.
And remember:
The best declaration is not the shortest one. It's the one that communicates the intent of the code most clearly.
That is the real difference between writing C# that merely compiles and writing C# that other developers enjoy maintaining.
Quick Cheat Sheet
// ✅ Type is obvious
var customer = new Customer();
// ✅ Complex construction
var customers = new List<Customer>();
// ✅ LINQ
var activeCustomers = customers
.Where(c => c.IsActive)
.ToList();
// ✅ Anonymous type
var result = new
{
Id = 1,
Name = "John"
};
// ✅ Abstraction is important
IOrderRepository repository =
new SqlOrderRepository();
// ✅ Domain meaning is useful
decimal orderTotal = CalculateOrderTotal();
// ❌ Type is unclear
var result = Execute();
// ❌ Meaningful type is hidden
var repository = CreateRepository();
The rule is simple:
Use
varwhen the type is obvious. Use an explicit type when the type adds meaning.

Comments
Post a Comment