AlgoMaster Logo

var Keyword (Implicit Typing)

Last Updated: May 17, 2026

9 min read

C# is statically typed, but you don't always have to write the type out by hand. The var keyword lets the compiler figure out the type of a local variable from the value you assign to it. The variable is still strongly typed, the compiler just saves you the keystrokes. This lesson covers what var actually does, the rules around when you can and can't use it, and the cases where it makes code clearer versus the cases where it hides important information.

What var Actually Means

When you write var name = "Alice";, the compiler looks at the right side, sees a string literal, and types the variable as string. The result is identical to string name = "Alice"; in every way the runtime cares about. The compiled IL contains a string variable, not a var variable. There is no var type.

Both variables are string. The var keyword is a compile-time convenience called type inference. It's not a special kind of variable, and it's not the same as the var keyword in JavaScript (which is dynamically typed) or the dynamic type in C# (which defers type checking to runtime).

This distinction matters because the misunderstanding is common. A reader coming from JavaScript or Python might assume var in C# means "the type can change later." It cannot. Once the compiler infers a type, that type is fixed for the lifetime of the variable.

The second line fails to compile with CS0029: Cannot implicitly convert type 'string' to 'int'. The compiler inferred stockCount as int on line 1, and from that point on, the variable is an int. Reassigning it to a string is the same kind of error you'd get with int stockCount = 10; stockCount = "out of stock";.

Compile-Time, Not Runtime

The work var does happens entirely during compilation. By the time your program runs, there is no var anywhere in the compiled assembly. The diagram below shows what happens when the compiler sees var price = 19.99m;.

The compiler looks at the literal 19.99m. The m suffix marks it as decimal, so price is inferred as decimal. From that point on, the variable behaves exactly as if you'd written decimal price = 19.99m;. There is no runtime cost. There is no boxing. There is no dynamic dispatch.

That's why var is sometimes called implicit typing: the type is still there, you just didn't type it out.

Compare that with dynamic, which is a separate C# type that defers all member resolution to runtime:

dynamic is a runtime feature, with real runtime cost. var is a compile-time shortcut, with zero runtime cost. The two look similar at the syntax level and behave completely differently. If you remember nothing else, remember that one.

The Rules

var has a small set of rules the compiler enforces. They all come from the same principle: the compiler must be able to infer a single, unambiguous type from the right-hand side at compile time.

Rule 1: Must Be Initialized in the Same Statement

The compiler infers the type from the initializer. No initializer, no inference.

This fails with CS0818: Implicitly-typed variables must be initialized. The compiler can't look ahead to line 2 to guess what type quantity should be. The fix is to combine declaration and assignment:

Rule 2: Can't Be Assigned Just null

null doesn't have a type on its own, it's a value that's compatible with many types. The compiler can't pick one.

This fails with CS0815: Cannot assign <null> to an implicitly-typed variable. You have to tell the compiler which type you mean:

You can use var with a typed expression that happens to evaluate to null, though. var name = (string?)null; works because the cast pins down the type.

Rule 3: The Type Is Fixed After Inference

Once the compiler picks a type, you can't reassign the variable to a value of a different, incompatible type.

Fails with CS0029. orderId is int, and "ORD-1001" is a string. Static typing still applies, you just didn't get to spell the type out.

Rule 4: Local Variables Only (Mostly)

var works for local variables inside a method, for foreach loop variables, for for loop counters, and in using declarations. It does not work for:

  • Fields on a class or struct. You can't write public var Name;. Fields need an explicit type.
  • Method parameters. You can't write void Add(var item). Parameters need an explicit type. The one exception, added in C# 10, is lambda parameters, where the compiler can infer types from the delegate's signature.
  • Return types. You can't write public var GetName(). Return types need an explicit type.

Both lines fail. Fields and return types must be declared explicitly. The fix:

The reasoning is partly historical and partly about readability. A class's public surface (its fields, properties, methods) is part of its contract with the outside world. Letting the compiler hide those types behind var would make that contract harder to read and harder to keep stable across versions.

When var Helps

The strongest case for var is when the type is long, obvious, or both. Repeating it on both sides adds noise without adding information.

Constructor calls where the type is right there:

The new on the right tells you exactly what you're getting. Writing List<Product> cart = new List<Product>(); is more characters for the same information.

LINQ projections, where the result is often an anonymous type or a generic interface:

The full type of groupedByCustomer is IEnumerable<IGrouping<int, Order>>. The full type of pendingOrderTotals is IEnumerable<<anonymous type>>. Spelling those out adds clutter without helping the reader.

`foreach` loops over a typed collection:

The collection's element type is Product, so the loop variable is Product. The reader can see that from the collection's declaration two lines up.

Long generic types:

Versus:

The var version says the same thing with less repetition. Modern C# also has target-typed `new` (covered at the end of this lesson) for the same problem from the other direction.

When var Hurts

var is a tool, not a default. Reach for an explicit type when reading the code without an IDE wouldn't tell you what's going on.

Numeric literals where the exact type matters:

What is the type of price? In C#, a decimal literal with no suffix is a double, so price is double. If you wanted decimal for money (which you do), this is a bug waiting to happen. The explicit form makes the intent unmistakable:

The same problem applies to integer literals and long, float, and decimal suffixes. When the literal's type isn't visually obvious, prefer the explicit declaration.

Return values where you have to look up the method's signature:

What's result? A bool? An Order? A Task<OrderResult>? Unless the reader knows what ProcessOrder returns, the line is opaque. With an explicit type, the question doesn't come up:

Casts and conversions where the conversion is the point:

works, but the var adds nothing. The cast already names the type. Either form is fine, but the explicit version reads more naturally:

The Microsoft style guidance, reflected in the default Roslyn analyzers shipped with .NET, lands on a simple rule: use var when the type is apparent from the right side, and use an explicit type when it isn't. "Apparent" is judgment, but constructor calls, casts, and literal initializers with clear suffixes all qualify. Method return values usually don't.

Side-by-Side: When to Use var vs Explicit

SituationUse var?Reason
var cart = new List<Product>();YesType is right there in the new.
var price = 19.99;NoReader can't tell if this is double, decimal, or float without thinking.
var customers = repository.GetAll();NoMethod return type is invisible at the call site.
var orderDate = DateTime.Now;YesDateTime.Now is a well-known property returning DateTime.
foreach (var item in cart.Items)YesElement type is visible from the collection.
var grouped = orders.GroupBy(o => o.Status);YesThe full LINQ type is long and unhelpful to spell out.
var couponCode = null;NoWon't compile.
var lookup = new Dictionary<string, List<Order>>();YesAvoids repeating the long generic on both sides.
var total = (decimal)items.Sum(i => i.Price);OptionalCast names the type. Either form is fine.
var customer = await GetCustomerAsync(id);Use judgmentCustomer from the method name is plausible, but Customer? or a wrapper type isn't visible. Explicit is safer.

The pattern: prefer var when the type is obvious from the right side of the assignment, prefer the explicit type when it isn't, and never use var when it would compile to a type the reader wouldn't guess.

var and Anonymous Types

There's one place where var isn't just a style choice, it's a requirement. Anonymous types are types the compiler generates on the fly when you use the new { ... } syntax without a class name. They have no name you can write down, so var is the only way to declare a variable of one.

The compiler generates a class with three properties (Name, Price, InStock) and gives it an internal, unspellable name. From your code's point of view, the only handle on that type is the var variable. If you tried to write the type explicitly, you wouldn't be able to, because the type's actual name is something like <>f__AnonymousType0.

Anonymous types come up most often inside LINQ queries, where you're projecting a few properties out of a larger object:

The Select projects each Order into a smaller object with just three properties. There's no named class for that shape, so var is the only declaration that works. This pattern is so common in LINQ code that you'll see var almost everywhere LINQ shows up.

Target-Typed new (C# 9)

var infers the type from right to left: the compiler looks at the value and gives the variable that type. Target-typed new, added in C# 9, does the opposite. It infers the constructor's type from left to right: you write the type once on the left, and the new expression on the right reuses it.

The new() with no type after it tells the compiler "use the type from the left side." It's a different angle on the same readability problem var solves: when you'd otherwise have to write the same long type twice, target-typed new lets you write it once on the left, and var lets you write it once on the right.

The two features overlap, and you can pick whichever reads better for a given case. Most teams pick one as a default and use the other when it fits. The advantage of target-typed new is that the variable's type stays visible in its declaration, which can help in fields and method signatures where var isn't allowed at all:

That field declaration is valid. private readonly var _ordersByCustomer = new Dictionary<int, List<Order>>(); is not, because var doesn't work on fields. Target-typed new works in places var can't.

Summary

  • var is compile-time type inference. The compiler reads the right side, picks a type, and treats the variable as that type from then on. There is no var at runtime.
  • var is not dynamic. dynamic defers type checking to runtime and has a real cost. var is a pure compile-time convenience with zero runtime cost.
  • var requires an initializer in the same statement, can't be assigned a bare null, and locks in its type after the first assignment.
  • var works for local variables, foreach and for loop variables, and using declarations. It does not work for fields, method parameters (except lambda parameters in C# 10+), or return types.
  • Use var when the type is apparent from the right side: new expressions, anonymous types, LINQ projections, long generic types, foreach over typed collections.
  • Avoid var when the right side doesn't make the type clear: numeric literals where the suffix matters, method return values, anywhere a reader would have to look up another file to know the type.
  • Anonymous types (new { Name = "Alice", Price = 99m }) have no spellable name, so var is the only declaration form that works for them.
  • Target-typed new (C# 9) is the mirror image of var: the type goes on the left and new() reuses it on the right. It works in places var doesn't, including fields.