C# Variables
A variable is a named place where a C# program stores a value while it runs. Variables let you remember data, update it, calculate with it, and pass it to other parts of your program. C# variables are strongly typed, which means each variable has a specific type such as int, string, bool, or decimal, and the compiler checks that you use the value correctly.
Overview: How C# Variables Work
A variable declaration tells the compiler three important things: the variable’s type, its name, and optionally its initial value. For example, int score = 90; declares a local variable named score that stores a whole number. After declaration, code in the same scope can read the variable, assign a new compatible value to it, or use it inside expressions.
C# is statically typed. The type of a local variable is known at compile time, before the program runs. This gives the compiler enough information to catch many errors early. If you declare int age = 16;, C# will allow arithmetic such as age + 1. It will not allow age = "sixteen"; because a string is not an integer. This type checking is one reason C# programs can be refactored and maintained safely in large applications.
Variables are not all stored the same way internally. Local variables that hold simple value types, such as int, double, bool, and decimal, directly contain their value. Local variables that hold reference types, such as string or most class objects, hold a reference to an object managed by the runtime. A string variable does not contain every character inline in the local variable slot; it refers to a string object. The CLR manages object memory and can reclaim objects that are no longer reachable.
Assignment changes what a variable currently holds. With value types, assignment copies the value. With reference types, assignment copies the reference, so two variables can refer to the same object. Strings are reference types, but they are immutable, meaning string operations create new strings instead of changing the existing string object. You will see reference sharing more clearly when you work with arrays, lists, and classes later.
Variables also have scope and lifetime. Scope is the region of code where a variable name can be used. A local variable declared inside Main can be used after its declaration until the end of the surrounding block. A variable declared inside an if block or loop block normally cannot be used outside that block. Lifetime is how long the storage exists at runtime; local variables exist while their method call is active, while objects they reference may live longer if something else still references them.
Syntax
type variableName = initialValue;
variableName = newValue;
var inferredName = initialValue;
const type ConstantName = constantValue;
| Part | Meaning |
|---|---|
type |
The kind of value the variable can hold, such as int, string, bool, or decimal. |
variableName |
The identifier used to read or assign the variable later. Local variables usually use camelCase. |
initialValue |
The first value assigned to the variable. Local variables must be definitely assigned before they are read. |
var |
Asks the compiler to infer the variable’s type from the initial value. The type is still fixed after that. |
const |
Declares a compile-time constant. Its value must be known when the program is compiled and cannot be changed. |
These declarations compile as ordinary statements:
int count = 0;
string course = "C#";
var nextCount = count + 1;
const double PassingScore = 70.0;
Examples
Declaring and Updating Variables
using System;
class Program
{
static void Main()
{
string studentName = "Ava";
int points = 10;
bool isEnrolled = true;
points = points + 5;
Console.WriteLine($"Student: {studentName}");
Console.WriteLine($"Points: {points}");
Console.WriteLine($"Enrolled: {isEnrolled}");
}
}
Output:
Student: Ava
Points: 15
Enrolled: True
The variables begin with initial values. The statement points = points + 5; reads the old value of points, adds five, and assigns the result back to the same variable. The bool value prints as True because that is the standard text form used by .NET.
Using Variables in Expressions
using System;
class Program
{
static void Main()
{
int apples = 6;
int oranges = 4;
int totalFruit = apples + oranges;
double averagePerBasket = totalFruit / 2.0;
Console.WriteLine($"Apples: {apples}");
Console.WriteLine($"Oranges: {oranges}");
Console.WriteLine($"Total fruit: {totalFruit}");
Console.WriteLine($"Average per basket: {averagePerBasket}");
}
}
Output:
Apples: 6
Oranges: 4
Total fruit: 10
Average per basket: 5
Variables can be combined in expressions. totalFruit stores the result of adding two int variables. The expression totalFruit / 2.0 uses 2.0, a double literal, so the division is floating-point division instead of integer division. That matters when the result is not a whole number.
A Realistic Receipt Calculation
using System;
using System.Globalization;
class Program
{
static void Main()
{
const decimal TaxRate = 0.0825m;
string item = "Desk lamp";
int quantity = 3;
decimal unitPrice = 19.99m;
decimal subtotal = quantity * unitPrice;
decimal tax = subtotal * TaxRate;
decimal total = subtotal + tax;
Console.WriteLine($"Item: {item}");
Console.WriteLine($"Quantity: {quantity}");
Console.WriteLine($"Subtotal: {subtotal.ToString("F2", CultureInfo.InvariantCulture)}");
Console.WriteLine($"Tax: {tax.ToString("F2", CultureInfo.InvariantCulture)}");
Console.WriteLine($"Total: {total.ToString("F2", CultureInfo.InvariantCulture)}");
}
}
Output:
Item: Desk lamp
Quantity: 3
Subtotal: 59.97
Tax: 4.95
Total: 64.92
This example uses several variable types together. decimal is a good choice for base-10 money calculations because it avoids many binary floating-point surprises. TaxRate is a constant because the program should not accidentally assign a new tax rate later in the method.
How Variables Work Step by Step
- The compiler reads a declaration such as
int points = 10;and records thatpointsis anintlocal variable in the current block. - The initializer
10is checked against the variable type. Because10is a validintliteral, the declaration is accepted. - When the compiler sees
points = points + 5;, it checks thatpointshas already been assigned, that+is valid for integers, and that the result can be stored back into anint. - The compiler emits intermediate language instructions that reserve local slots, load values, perform operations, and store results.
- At runtime, the CLR executes those instructions. Local values are stored in method-local storage managed by the runtime, and reference-type objects are tracked by the garbage collector.
C# also has definite assignment rules. A local variable does not automatically become usable just because you declared it. If the compiler cannot prove that a local variable has received a value before it is read, compilation fails. This prevents unpredictable reads of uninitialized local data.
Common Mistakes
Reading a Local Variable Before Assignment
int score;
Console.WriteLine(score);
This does not compile. The variable exists, but no value has been assigned before it is read. Assign a value first, even if that value is only a sensible default.
int score = 0;
Console.WriteLine(score);
Output:
0
Assuming var Means Dynamic
var level = 3;
level = "advanced";
This does not compile. var does not create a variable whose type can change. It tells the compiler to infer the type once. Here, level is inferred as int, so a string cannot be assigned later.
var level = 3;
level = 4;
Console.WriteLine(level);
Output:
4
Losing Precision With Integer Division
using System;
class Program
{
static void Main()
{
int completed = 3;
int total = 4;
double ratio = completed / total;
double correctedRatio = completed / (double)total;
Console.WriteLine(ratio);
Console.WriteLine(correctedRatio);
}
}
Output:
0
0.75
The first division uses two int values, so C# performs integer division and discards the fraction before assigning the result to double. Cast one operand or use a floating-point literal when fractional results matter.
Best Practices
- Use clear camelCase names for local variables, such as
studentName,totalPrice, andisActive. - Initialize local variables close to where you first use them.
- Prefer explicit types when the type teaches the reader something important, such as
decimal unitPrice. - Use
varwhen the type is obvious from the right side, such asvar message = "Saved";. - Use
constfor true compile-time constants that should never change. - Choose numeric types intentionally:
intfor whole counts,doublefor scientific-style measurements, anddecimalfor money-like decimal values. - Keep variable scope as small as practical so names do not leak into unrelated code.
- Do not reuse one variable for unrelated meanings; create a new well-named variable instead.
Practice Exercises
- Create variables for a book title, page count, and whether you have finished it. Print all three values with labels.
- Write a program that stores a test score and maximum score, calculates the percentage as a
double, and prints it. - Create a receipt program with
const decimal TaxRate, an item name, quantity, and unit price. Print the subtotal, tax, and total.
Summary
- A C# variable is a named storage location with a fixed compile-time type.
- Declarations can include an initial value, and local variables must be assigned before they are read.
- Assignment replaces the variable’s current value or reference with a new compatible one.
varuses type inference, but the inferred type is still static and cannot change later.constcreates a value that is known at compile time and cannot be reassigned.- Scope controls where a variable name can be used, and smaller scopes usually make code easier to understand.
