C# Variable Declaration: Syntax and Practical Usage
c# variable declaration: Learn how to declare variables in C# with explicit types, var, and nullable annotations, and understand the tradeoffs for readability and main...
C# variable declaration follows a simple pattern: a type, a name, and an optional initial value. The simplest form is:
int count;
This declares an integer variable named count without assigning a value. Until it is assigned, the variable holds the default value for its type, which is 0 for numeric types, false for bool, and null for reference types. You can also declare and initialize in one step:
int count = 10; string name = "Ada";
The type can be a built-in type, a user-defined class, a struct, an interface, or a generic type. The declaration must appear before the variable is used, and the name must follow C# identifier rules.
Using var for Implicit Typing
C# provides the var keyword to declare a variable whose type is inferred from the initializer at compile time. This is not dynamic typing; the compiler determines the exact type and enforces it statically.
var count = 10; // int var name = "Ada"; // string var items = new List<int>(); // List<int>
var is required when the type is anonymous, such as the result of a LINQ Select that returns an anonymous type. It is also convenient when the type name is long and the initializer makes it obvious. However, using var when the type is not clear from the right-hand side can hurt readability.
var result = GetValue(); // What type is result?
In this case, an explicit type is usually better because it documents the contract at the point of declaration.
Declaring Nullable Value Types
Value types like int and bool cannot normally hold null. To allow null, you declare a nullable value type using the ? suffix:
int? maybeCount = null; bool? flag = null;
The Nullable<T> struct underlies this syntax. Accessing the value requires checking HasValue or using the ?? operator to provide a default:
int actual = maybeCount ?? 0;
Nullable reference types are a separate feature controlled by the #nullable context. When enabled, the compiler warns if a reference type that is not marked nullable might receive null. You can declare a reference type as nullable with string?:
string? name = null;
This annotation is a compile-time contract that helps prevent NullReferenceException without changing runtime behavior.
Declaration vs Initialization and Default Values
A variable that is declared but not initialized still has a well-defined default value. For local variables, the compiler requires definite assignment before use; you cannot read a local variable before assigning it. For fields, the default value is assigned automatically.
class Example { int _count; // default 0 string? _name; // default null }
Local variables must be explicitly assigned:
int x; Console.WriteLine(x); // Compiler error: use of unassigned local variable
This rule prevents accidental use of uninitialized state. You can initialize with default explicitly:
int x = default; // 0 string? s = default; // null
Variable Scope and Lifetime
The scope of a variable is the region of code where it can be referenced. Local variables are scoped to the block in which they are declared, typically a method or a { } block. A variable declared inside a for loop is not accessible outside it.
for (int i = 0; i < 10; i++) { // i is visible here } // i is not visible here
Member variables (fields) have class or struct scope and live as long as the containing object. Choosing the right scope is part of designing maintainable code: local variables reduce coupling and make methods easier to reason about.
Maintainability and Readability Tradeoffs
The choice between var and explicit types is a style decision that affects code review and maintenance. The C# team's guidance is to use var when the type is obvious from the initializer, and explicit types when the type is not apparent. There is no performance difference; var is resolved at compile time and produces the same IL as an explicit declaration.
Teams should agree on a convention and apply it consistently. For public APIs, explicit types are often clearer because they document the contract. Inside method bodies, var can reduce visual noise when the type name is long, such as with nested generics.
Dictionary<string, List<Order>> ordersByCustomer = GetOrders(); var orders = GetOrders(); // type is Dictionary<string, List<Order>>
Both compile to identical code. The decision is about readability, not runtime behavior.
Common Mistakes and How to Avoid Them
One common mistake is using var with a method that returns a different type than expected, leading to a compile-time error when the inferred type does not match later usage. Another is forgetting to initialize a local variable and then trying to read it, which the compiler rejects.
When working with nullable value types, developers sometimes assume that int? can be used directly in arithmetic. You must convert to a non-nullable value first:
int? a = 5; int? b = null; int sum = a.Value + b.Value; // throws InvalidOperationException
Use ?? to provide a neutral value:
int sum = (a ?? 0) + (b ?? 0);
Finally, remember that var cannot be used for a declaration without an initializer. The compiler needs the initializer to infer the type.
var x; // error
These patterns cover the majority of variable declaration issues you will encounter in everyday C# development.