A variable is a named storage location with a fixed type. In C# you declare it with a type and a name, and optionally give it a value in the same statement. The type never changes afterwards: an int variable holds whole numbers for as long as it exists.
Output:
Priya bought 5 items for 20.25
10
Assigning a value of the wrong type is a compile error: quantity = "five"; fails with CS0029 (cannot implicitly convert type 'string' to 'int'). Converting between types is explicit; see type conversion.
var: letting the compiler infer the type
var declares a local variable whose type is inferred from its initializer. It is not dynamic typing: the type is fixed at compile time, exactly as if you had written it out.
Output:
String
Int32
Decimal
Double
List`1
var has three rules. It only works for local variables (not fields or parameters). The variable must be initialized in the declaration: var x; is error CS0818, "Implicitly-typed variables must be initialized". And the initializer must have a type: var nothing = null; does not compile, because null alone has no type.
When to use it is a matter of team style. The usual guideline is to use var when the type is obvious from the right side, and write the type when it is not:
var orders = new List<Order>(); // obvious: var is fine
var reader = new StreamReader(path); // obvious
decimal discount = CalculateDiscount(); // not obvious: name the type
int count = items.Count(); // makes the intent clear
A subtle trap: var total = 0; makes total an int, so adding 2.5 to it later fails, and var price = 10; is an int, not a decimal. When the literal's type is not the one you want, write the type or add a suffix (10m, 0.0).
Scope
A local variable exists from its declaration to the end of the block { } it was declared in. Variables declared in a loop header or an if body are not visible after it.
Output:
high
240
Unlike C and C++, C# does not let an inner block declare a local with the same name as one in an enclosing block (error CS0136): the name must mean one thing throughout a method. Two sibling blocks can reuse a name, as two separate for loops each declaring i do.
Definite assignment
Local variables have no default value. The compiler tracks every path through the method and refuses to compile if a variable might be read before it has been assigned:
int discount;
if (isMember)
{
discount = 10;
}
Console.WriteLine(discount);
// error CS0165: Use of unassigned local variable 'discount'
Fix it by initializing at the declaration (int discount = 0;) or by assigning in every branch (add an else). Fields and array elements are different: they are automatically set to the default value of their type (0, false, null).
const: compile-time constants
A const is a value fixed at compile time. It must be initialized with a constant expression (a literal, another const, or arithmetic on them), and it can only be a number, char, bool, string, enum or null.
Output:
Price in EUR
120.00 EUR
350
A const field is implicitly static, so it is accessed through the type name (Pricing.VatRate), and writing static const is an error. The compiler copies the value into every place that uses it, which is why consts cost nothing at run time, and also why a public const in a library should be a value that will never change (like the number of days in a week).
readonly and static readonly
A readonly field can be assigned only in its declaration or in a constructor of its class. After construction it cannot change. Unlike const, its value is computed at run time, can be any type, and can differ between objects.
Output:
ACC-17 opened 2024-05-02
Launch: 2020-01-15
basic, pro
The last lines show the common misunderstanding: readonly protects the field, not the object it points to. Plans will always refer to the same array, but the array's elements can still change. For truly immutable collections use ReadOnlyCollection<T> or ImmutableArray<T>.
Summary of the three:
const | readonly | static readonly | |
|---|---|---|---|
| Value known | At compile time | At run time | At run time |
| Allowed types | Numbers, char, bool, string, enums, null | Any | Any |
| Set in | Declaration only | Declaration or constructor | Declaration or static constructor |
| Per object or shared | Shared (implicitly static) | Per object | Shared |
| Local variables | Yes (const int x = 1;) | No | No |
Naming conventions
C# names are case sensitive (total and Total are different variables) and must start with a letter or underscore. Microsoft's conventions, followed by nearly all C# code:
- Local variables and parameters: camelCase (
orderCount,unitPrice). - Constants, properties, methods, classes and public fields: PascalCase (
MaxItems,VatRate). - Private fields: _camelCase with a leading underscore (
_balance), a widespread convention in .NET code. - Booleans read as questions:
isActive,hasDiscount,canRetry. - Avoid abbreviations and Hungarian prefixes (
strName,iCount).
A C# keyword cannot be a name, unless you prefix it with @: var @class = "5B"; is legal, which is occasionally useful for generated code or JSON field names.
Swapping and multiple assignment
Since C# 7, tuples let you assign several variables in one statement, which gives a one-line swap:
Output:
20 10
Lisbon: 545,000
The second form is deconstruction: it declares city as a string and population as an int from a tuple. More in tuples.
Frequently Asked Questions
What is var in C#?
var tells the compiler to infer a local variable's type from the value it is initialized with: var count = 5; declares an int. The variable is still statically typed and cannot later hold a string. var only works for local variables that are initialized in the same statement.
What is the difference between const and readonly in C#?
A const is a compile-time constant: its value must be known when compiling (numbers, strings, bool, null), it is implicitly static, and the value is copied into every place that uses it. A readonly field is set once at run time, in its declaration or in a constructor, can hold any type, and can differ per object.
When should I use static readonly instead of const?
Use static readonly for a shared value that cannot be a compile-time constant, such as a DateTime, an array or an object, or for a public value that might change between versions of a library. Because const values are copied into calling assemblies, changing a public const requires recompiling every assembly that uses it.
What does "use of unassigned local variable" mean in C#?
Error CS0165: the compiler found a path where a local variable is read before any value was assigned to it. Local variables have no default value in C#. Initialize the variable when you declare it, or make sure every branch of the if/switch assigns it before it is used.
Should I use var or explicit types in C#?
Both are fine; teams pick a style. A common rule is to use var when the type is obvious from the right side (var list = new List<string>();) and write the type when it is not (decimal total = GetTotal();). The .NET runtime codebase follows roughly that rule.