Storing data that changes — and data that stays the same — in C#.
Imagine you're building a calculator app. You need to store the numbers the user enters, the result of each operation, and maybe a fixed value like PI that never changes. Every time the user presses a button, the numbers in memory change — but PI stays exactly the same.
That's the core difference between variables and constants in C#. Variables hold data that can change as your program runs. Constants hold data that stays fixed forever.
Every C# program — from a simple console app to a massive enterprise system — uses variables and constants constantly. Understanding them is the first step toward writing real code that works with data.
Variable = A named storage location in memory whose value can change during program execution.
Constant = A named storage location whose value is fixed at compile time and cannot change afterward.
Variables are named memory locations that store values. You declare a variable by specifying its type and name, and you can assign a value to it. The value can be changed any number of times during the program's lifetime.
Constants are values that are known at compile time and do not change for the entire lifetime of the program. They are declared using the const keyword and must be assigned a value at declaration. The compiler replaces constant references with their literal values during compilation.
When you write a program, you need to work with data. A user's name, a bank balance, the current time, a product price — these are all pieces of information your program needs to store, retrieve, and manipulate.
Imagine if you had to remember the memory address of every piece of data you used. It would be nearly impossible to write any program larger than "Hello, World!"
Variables give you a named way to refer to data. Instead of remembering that the user's age is at memory address 0x7FFD8A3F9C10, you can simply use the name age. Constants give you a way to give meaningful names to fixed values — so instead of writing 3.14159 everywhere, you write PI.
Variables and constants are how your program "remembers" data. Without them, every piece of information would have to be re-entered or recalculated every time it was needed.
Here's how variables and constants fit into the C# type system and memory:
int, bool, double, structstring, object, class, arrayconst)
string can be constreadonly)
Let's trace what happens when you declare and use variables and constants in C#:
int age; // Declaration — memory is reserved, but no value is set yet
You tell the compiler: "I need a storage location named age that can hold an int." The compiler reserves memory for it.
age = 25; // Assignment — the value 25 is stored in the reserved memory
You write a value into the memory location. Now age holds the value 25.
const double PI = 3.14159; // Must be assigned at declaration
The compiler sees PI and replaces every use of PI with 3.14159 at compile time. No memory is allocated at runtime.
double circumference = 2 * PI * radius; // PI is replaced with 3.14159
The variable radius holds a value from user input or calculation. The constant PI provides the fixed mathematical value.
Here's a complete C# program showing variables and constants in action:
// ── Variables ──
string userName = "Alice"; // Can change later
int score = 0; // Starts at 0, can increase
bool isGameOver = false; // Tracks game state
// ── Constants ──
const int MAX_SCORE = 100; // Fixed maximum
const string GAME_TITLE = "Super C# Adventure";
// ── Using them ──
Console.WriteLine($"Welcome to {GAME_TITLE}, {userName}!");
score += 10; // Variable changes
if (score >= MAX_SCORE) // Constant used in condition
{
isGameOver = true;
Console.WriteLine($"You win, {userName}!");
}
What's happening:
userName, score, isGameOver are variables — their values can change as the game progresses.MAX_SCORE and GAME_TITLE are constants — their values are fixed and known at compile time.score starts at 0 and increases by 10 each time the player scores.MAX_SCORE sets the winning threshold — it never changes.Consider an e‑commerce checkout system. Here's how variables and constants would be used:
// ── Constants (business rules that never change) ──
const decimal TAX_RATE = 0.08m; // 8% sales tax
const decimal FREE_SHIPPING_THRESHOLD = 50.00m;
const decimal STANDARD_SHIPPING = 5.99m;
// ── Variables (data that changes per order) ──
string customerName = "Jane Doe";
var cartItems = new List<Product>(); // C# 14: collection expression
decimal subtotal = 0.00m;
decimal tax = 0.00m;
decimal shipping = 0.00m;
decimal total = 0.00m;
// ── Calculate order totals ──
foreach (var item in cartItems)
{
subtotal += item.Price * item.Quantity; // Variable changes
}
tax = subtotal * TAX_RATE; // Constant used
if (subtotal >= FREE_SHIPPING_THRESHOLD) // Constant used
{
shipping = 0.00m;
}
else
{
shipping = STANDARD_SHIPPING; // Constant used
}
total = subtotal + tax + shipping; // Final variable
// ── Output ──
Console.WriteLine($"Order for {customerName}: ${total:F2}");
What's happening:
TAX_RATE, FREE_SHIPPING_THRESHOLD, STANDARD_SHIPPING) represent fixed business rules that rarely change.customerName, subtotal, tax, shipping, total) hold data specific to each order.You have a box with a label — age. You can put a number in it, take it out, and replace it with a different number later. The box stays the same; the contents change.
You have a plaque with PI = 3.14159 engraved into it. You can read it, but you can never change it. The value is fixed forever.
age, score, subtotal)25, 0, 42.50)MAX_SCORE, PI)Let's look at what actually happens in memory and at compile time when you use variables and constants:
int age = 25; const double PI = 3.14159;
25 is written to that memory locationage is a symbolic reference to that memory addressPIPI in your code is replaced with 3.14159 directly in the ILage = 26; — The new value is written to the same memory location25) is overwritten and lostconst — Compile‑time constant. Inlined. Only value types and string. Must be assigned at declaration.
readonly — Runtime constant. Not inlined. Can be reference types. Can be assigned in the constructor.
Remember: readonly is "set once, then never changed" — but it's not a compile‑time constant. It's evaluated at runtime.
var is statically typed — the compiler infers the type from the initialization expression. It's not a "loose" type like dynamic or JavaScript's var.
var name = "Alice"; // name is string — compiler knows this
name = 42; // Compiler error: can't assign int to string
Use var when the type is obvious from the right‑hand side. Use explicit types when the type is not obvious or when you want to be explicit for clarity.
int count;
Console.WriteLine(count); // Compiler error: unassigned local variable
Fix: Always initialize variables before reading them.
int count = 0;
Console.WriteLine(count); // Works — outputs 0
const double PI = 3.14159;
PI = 3.14; // Compiler error: cannot assign to const
Fix: Use a variable if the value needs to change, or use readonly if it's set once in a constructor.
double pi = 3.14159; // Variable — can change
pi = 3.14; // Works
const DateTime Now = DateTime.Now; // Compiler error: DateTime.Now is not a compile-time constant
Fix: Use static readonly for runtime‑evaluated values.
static readonly DateTime Now = DateTime.Now; // Works
int a = 5; // Value type — stored on stack
int b = a; // Copy of value — b is 5, a is 5
a = 10; // b is still 5 — separate copies
string s1 = "Hello"; // Reference type — stored on heap
string s2 = s1; // Both point to the same string object
s1 = "Goodbye"; // s2 still points to "Hello" — strings are immutable
Fix: Understand that value types copy data; reference types copy references.
MAX_RETRIES instead of 3.DateTime.Now, configuration values, dependency injections. Best practice: Prefer readonly over const when you're not certain the value is truly compile‑time constant. readonly gives you more flexibility and avoids versioning issues when constants change.
const.var when the type is obvious; use explicit types when clarity matters more.You've seen how variables hold data that can change and constants hold fixed values. Let's test your understanding of when and how to use each.
1. Which of the following correctly declares a constant in C#?
Correct: B
Why B is correct: The const keyword is used to declare a compile‑time constant. The value must be assigned at declaration and cannot change afterward.
Why A is incorrect: This declares a variable, not a constant. PI could be reassigned later.
Why C is incorrect: readonly is a runtime constant. It can be assigned in the constructor, not just at declaration. It's not a compile‑time constant like const.
Why D is incorrect: static makes a variable belong to the type rather than an instance, but it's still a variable that can change.
Reinforcement: const is for values that are truly fixed and known at compile time. Use readonly when the value is set at runtime but then never changes.
2. What will this code output?
int x = 5;
int y = x;
x = 10;
Console.WriteLine(y);
Correct: B
Why B is correct: int is a value type. When you assign y = x, you create a copy of the value. Changing x to 10 doesn't affect y, which remains 5.
Why A is incorrect: This would be true if int were a reference type, but it's a value type. The two variables are independent.
Why C is incorrect: The code is perfectly valid and compiles successfully.
Why D is incorrect: y was initialized to the value of x (which was 5 at that time), not 0.
Reinforcement: Value types (like int, bool, double, struct) copy data when assigned. Reference types (like string, class, array) copy references. This is a crucial distinction in C#.
3. You're building a banking application. The interest rate is set by the central bank and rarely changes. The account balance changes with every deposit and withdrawal. Which approach is correct?
Correct: B
Why B is correct: The interest rate is a fixed business rule that can be a compile‑time constant (const) if known at compile time, or readonly if loaded from configuration. The account balance must be a variable because it changes constantly.
Why A is incorrect: Account balance changes frequently — it cannot be a constant.
Why C is incorrect: Account balance cannot be a constant for the same reason. Interest rate could be either a constant or a variable, but it's better as a constant (or readonly) since it shouldn't change arbitrarily.
Why D is incorrect: readonly means the value is set once and never changes — that works for interest rate but not for account balance, which changes with every transaction.
Reinforcement: Choose const or readonly for values that are fixed. Use variables for values that change over time. Always match the storage mechanism to the data's behaviour.
4. What happens if you try to declare a constant using a value that's not known at compile time?
Correct: C
Why C is correct: const values must be known at compile time. The compiler must be able to evaluate the expression. For example, DateTime.Now is not a compile‑time constant, so const DateTime Now = DateTime.Now; will produce a compiler error.
Why A is incorrect: This is not a warning situation — it's a hard compile‑time error.
Why B is incorrect: const can't use runtime values. This is the whole point of readonly — for runtime‑evaluated values.
Why D is incorrect: The compiler doesn't "downgrade" a constant to a variable. You'll get an error and the code won't compile.
Reinforcement: If you need a value that's determined at runtime but won't change afterward, use readonly instead of const. readonly values are set at runtime (in the constructor) and then locked.
5. Consider this code snippet. Which statement about the userName variable is true?
string userName = "Alice";
userName = "Bob";
Console.WriteLine(userName);
Correct: C
Why C is correct: userName is a variable that holds a reference to a string. When you reassign it from "Alice" to "Bob", the variable now points to a different string object. The string "Alice" remains immutable, but the variable changed what it points to.
Why A is incorrect: You can reassign a string variable to a new string value. The string itself is immutable, but the variable can change.
Why B is incorrect: The output is "Bob" because the variable was reassigned before the WriteLine call.
Why D is incorrect: This would only happen with concatenation (e.g., userName += "Bob"), not with reassignment.
Reinforcement: "Immutable" means the object itself can't change, not that the variable can't change. This is a very common source of confusion for beginners. Strings are immutable, but string variables are still variables — they can be reassigned.
You've mastered variables and constants — the foundation of working with data in C#!
dotnetmadeeasy.com — Learn C# and .NET, the right way.