Summary#
Locals can declare an explicit type instead of var — int x = 5;, Order o = …;,
List<int> xs = …;. The declared type pins the binding, exactly C#: literal initializers apply the
C# constant conversion, non-literal initializers must be implicitly assignable, and every typed local
must be initialized at its declaration.
Signature#
<Type> <name> = <initializer>;
// Type: a scalar keyword, entity (incl. namespaced), Type?, Type[], List<T>/HashSet<T>/Dictionary<K,V>Description#
- A typed local must be initialized at its declaration —
int x;is refused (there is no definite-assignment analysis; initialize where you declare). - Literal initializers use the C# constant conversion: the literal is re-kinded when widening
(
int → long/decimal/double,decimal → double) — sodouble h = 2.5;compiles even though a bare2.5is decimal (Numeric types & literal suffixes). A non-representable constant refuses:int x = 2.5m;→cannot implicitly convert 'decimal' to 'int'. - Non-literal initializers widen by numeric rank (
int → long → decimal/double) but never across decimal↔double in either direction — C# has no implicit conversion between them (double x = someDecimal;is a pointed error). nullneeds a nullable declared type —int? x = null;, notint x = null;.- The pinned type drives downstream resolution — an entity-typed local navigates members
(
Order o = Order.First(); o.Total). - Decompile normalizes to
varwith the re-kinded literal (decimal d = 5;→var d = 5m;) — semantically identical; the same normalization const-inlining uses.
Examples#
entity Order { decimal Total; }
decimal Examples() {
int x = 5; // pins int
long big = 5; // constant conversion: the int constant becomes long
decimal d = 5; // → 5m
double h = 2.5; // works — the constant converts (a bare 2.5 is decimal)
int? maybe = null; // nullable declared type accepts null
Order? o = Order.FirstOrDefault(); // entity-typed local — `?`, because …OrDefault() may answer null
if (o != null) { return o.Total + d; }
return d + x + big + maybe ?? 0;
}⚠ The ? on o is the example, not a typo. A …OrDefault() read answers null when nothing matches, so a
non-nullable Order o would be holding a null the moment the table is empty — and every later read of it would be an
unguarded one. The compiler refuses that declaration and names both honest choices: Order? o if absent is a case you
handle, or First() if it is not, which fails loudly at the read instead of handing you a null that surfaces
somewhere else. This page carried the non-nullable form until 2026-08-27, when the check that catches it landed.
See also#
- Numeric types & literal suffixes — the literal kinds the constant conversion re-kinds between
- const —
const Type name = …;(the compile-time-constant sibling)