C# Variables and Constants
A variable gives a typed value a name you can use again. Learn how that value changes over time, why a calculated result does not update itself, and when a compile-time constant is a better choice than another mutable variable.
What you will be able to do
- Identify the type, name and initializer in a declaration.
- Distinguish declaration, initialization and later assignment.
- Trace the right-hand expression before storing a new value.
- Explain why copying an integer does not create a live link.
- Use var without assuming the variable can change type.
- Choose const for a supported value known at compile time.
- Recalculate dependent values when their inputs change.
A declaration connects a type, a name and a value
So far you have used a few named values to make reports. A variable lets you refer to a value by a meaningful name rather than repeating a literal throughout the program. For a simple local declaration, read type name = initializer; from left to right, then identify which value is available after that statement.
The type is a constraint, not just a description for a human reader. A whole-number quantity, a product name and a yes-or-no packing flag represent different kinds of information. This lesson introduces int, string and bool only as familiar examples; the next lesson examines type choices and ranges more carefully.
A variable name is not a label automatically shown to the user. The output calls choose what gets displayed. Likewise, declaring itemName does not create a database column or store an order permanently. These locals belong to the execution of this small console program.
Program.cs · Name the information in an order
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Item: Notebook
Quantity: 2
Ready to pack: True
Each declaration provides a type, a name and an initial value. string holds the item's text, int holds a whole-number quantity, and bool holds a true-or-false value. The bool literal is lowercase true in source; its ordinary console representation is True. These values describe this example only: no order is stored or sent to a packing system.
Read int quantity = 2; in four parts
int- The explicitly stated type. It determines which values and operations are valid for this local variable.
quantity- The local name used by later expressions. Choose a role-specific name and keep its spelling and capitalization consistent.
= 2- The initializer supplies the first value in this declaration. In a later assignment, the same equals symbol stores a new compatible value.
;- The statement terminator. The declaration does not continue onto the next statement just because the source looks related.
Declare, initialize and read are different actions
Declaring introduces the local name and its type. Initializing supplies its first value. A read uses the value in an expression or call. These actions can occur together in a declaration with an initializer, or an explicitly typed local can be declared before its first assignment.
Before reading a local, the compiler must be able to establish that it has been assigned. A bare int quantity; does not let the next call read an automatic zero. Assign a meaningful value before using it instead of adding an arbitrary zero simply to quiet a diagnostic. Some other C# storage categories have default-initialization rules; that does not override local definite-assignment checks.
Compare the next two programs. The working one assigns 2 before the read; the failing one never assigns a value. In the failing example, the output method is not reached because compilation has not succeeded. Fixing this is a source-data issue, not an indication that the .NET installation is broken.
Program.cs · Declare first, assign before reading
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Quantity: 2
The first statement introduces the local variable without supplying a value. The next statement is its first assignment, so the later read is valid. With an explicit type, declaration and first assignment can be separate. This is not a reason to defer every initializer: assigning a sensible value at the declaration is usually easier to follow when that value is already available.
Program.cs · A local does not become zero automatically
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Compilation fails: the local quantity is read before it is assigned.The local variable is declared, but no value has been definitely assigned before the read. The compiler rejects this program rather than printing a guessed zero. Fields and array elements have different initialization rules; do not transfer those rules to an unassigned local variable.
Assignment evaluates first, then replaces a value
In quantity = quantity + 1, evaluate the right-hand expression using the current quantity, then store the result on the left. The statement is a change to program state, not a mathematical claim that one fixed number equals itself plus one. The old value remains visible in any output printed earlier.
Use the type only when declaring that local. A later quantity = 3; assigns to it. A later int quantity = 3; in the same local scope attempts to introduce the name again and causes a declaration problem. Clear names matter, but inventing a new name for every update can make the changing state harder to follow.
The assigned value must be compatible with the variable's type. Reassigning an int from one whole number to another is normal. Assigning text such as three to it is not. The equals operator performs assignment; comparisons that ask whether values are equal use a different operator, which you will study with conditions and operators.
Program.cs · Update the current quantity
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Before: 2
After: 3
First quantity holds 2. The assignment evaluates the right side using that current value, producing 3, and then stores 3 in quantity. The earlier printed line remains 2. The type name appears in the declaration, not in this update: writing int quantity again in the same scope would attempt another declaration rather than update the existing variable.
A copy or calculation is not a live connection
For ordinary integer assignment, copying a variable copies its current integer value. The two names then refer to separate locals. If the original changes afterward, the copied integer stays as it was until another statement assigns a new value to it. Do not generalize this example into a rule that every object assignment makes an independent object copy.
A calculated initializer also produces a value at that moment. Multiplying a unit price and a quantity stores a subtotal, not a formula that watches both inputs. This is a common source of stale reports: the program updates the input, then prints a previously calculated result beside it.
The remedy depends on when the result is needed. Calculate it after the relevant inputs are final, or explicitly recalculate when they change. In these straight-line programs, you can identify the correct place by tracing statement order. Later, methods and properties provide other ways to structure derived results; they are not needed to solve today's examples.
Program.cs · Copy an integer value
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Original: 5
Copy: 2
The initializer for copiedQuantity reads the integer value 2 and copies it. Changing originalQuantity later does not update the separate copied value. This explanation is about ordinary integer value assignment; it is not a claim that assigning every future object type clones the object. Reference-type behavior is covered with classes and objects.
Program.cs · A calculated result is a snapshot
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Initial subtotal: 2400 cents
Changed quantity: 3
Stored subtotal: 2400 cents
Recalculated subtotal: 3600 cents
The multiplication runs where its statement is reached; it does not install a spreadsheet-style formula that reacts to future changes. After quantity becomes 3, subtotalCents still holds 2400 until the program evaluates and assigns the multiplication again. Integer cents keep this exercise about assignment, without introducing fractional money formats or checkout behavior.
var infers a type once; it does not make a variable untyped
With var quantity = 2;, the compiler obtains the type from the initializer. For this ordinary integer literal it infers int. A quoted initializer gives a string in the next declaration. The resulting locals still have compile-time types and normal assignment rules.
var needs an initializer from which a type can be inferred. Writing var quantity; leaves the compiler without that information. It is a facility for local declarations, not a universal replacement for every type name in every future class member or method signature. Use an explicit type in this lesson whenever it makes the example easier to understand.
Choose var for readability when the right side makes the type clear, not because you want the variable to accept unrelated values later. The two examples below use the same initial quantity: one keeps assigning compatible whole numbers, while the other tries to assign text and is rejected before execution.
Program.cs · var still has a fixed compile-time type
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Item: Notebook
Quantity: 5
The compiler infers int from the initializer 2 and string from the quoted initializer. The later whole-number assignment is valid because quantity is still an int. var saves you from spelling the type at that declaration; it does not remove the type or postpone type checking until the program runs.
Program.cs · An inferred integer cannot become text
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Compilation fails: the inferred int variable cannot receive a string.The first initializer already established the type. The text three is a string, not another whole-number quantity. Use a compatible numeric value for this quantity; do not switch to an unrelated type just to silence the error. Conversion and parsing are separate topics in later lessons.
const names a supported compile-time value
A local const declaration needs a type, a name and a constant initializer. It cannot be assigned another value later. This makes the fixed rule visible in the source and lets the compiler reject accidental reassignment. It does not make every calculated value in the program constant.
Use constants for supported values that genuinely belong in the source as compile-time facts or rules. MinutesPerHour = 60 is a useful example. A live price, a user preference or a value read at runtime should not become const merely because you do not expect it to change during one short run. Supported constant expressions can use other constants, but not an ordinary mutable local as their value source.
Naming conventions and language rules are separate. PascalCase helps distinguish constants in these examples, while camelCase identifies locals such as studyHours. Capital letters do not enforce const behavior. Later you will encounter readonly members with different initialization rules; do not treat readonly and const as interchangeable keywords.
Program.cs · Give a fixed rule a constant name
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Planned minutes: 120
MinutesPerHour is initialized with a compile-time constant expression and cannot be assigned another value afterward. studyHours can still change, and the multiplication produces an ordinary calculated local value. PascalCase for constant names is a readability convention; const, the supported type and the compile-time initializer supply the language behavior.
Program.cs · A constant cannot be reassigned
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Compilation fails: a constant is not an assignment target.Changing the rule in a later statement contradicts the declaration's constant meaning. If a value genuinely needs to vary, use an ordinary variable with a suitable name. For a minutes-per-hour conversion, changing it to 45 would also misrepresent the rule, so removing const would not make that change correct.
Program.cs · An ordinary variable is not a constant initializer
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Compilation fails: the initializer is not a constant expression.A compiler may be able to observe this variable's initial value, but quantity is still an ordinary mutable local, not a constant expression. Use int startingQuantity = quantity for a copied starting value, or give const a genuine constant initializer when that is the intended design. A value staying unchanged in one run does not automatically make it eligible for const.
Keep names meaningful and within the scope you can explain
Names such as quantity and subtotalCents reveal both a role and, when useful, a unit. The name subtotal without a unit can be ambiguous when a program uses both cents and formatted currency text. A good name reduces the need for a comment that merely translates an abbreviation.
Identifiers are case-sensitive: quantity and Quantity are different names. Use ordinary descriptive names rather than reserved keywords. A local declared inside a nested block is not available after that block ends. The syntax lesson demonstrated this boundary; introducing var does not change the scope rule.
Keep this lesson's model deliberately small: each complete editor runs separately, with its own local declarations. Renaming a local requires updating its references consistently. Saving an edit and running again starts this program again; it does not preserve the last run's quantity as application storage.
Guided repair: a changed quantity and an old subtotal
An order starts with two items at 1200 cents each, then its quantity changes to four. The final report must show quantity 4 and subtotal 4800 cents. Run the original and identify which local changed and which derived value did not.
Program.cs · Repair an out-of-date order total
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Quantity: 4
Subtotal: 2400 cents
The program compiles and prints a new quantity beside the old subtotal. Reading quantity in the first message does not update another variable. The required report is based on the final quantity, so the calculation must be performed after that change or explicitly recomputed before the subtotal is printed.
Repair checkpoints
- The original source compiles but prints a stale subtotal of 2400 cents.
- Recalculate the subtotal after the quantity update, or move its declaration after that update.
- Keep the unit price and quantity as the inputs; do not hardcode 4800.
- With final quantity 0, expect subtotal 0; with final quantity 1, expect 1200.
- This report has no checkout, tax calculation, persistence or quantity validation.
Reveal the repair and explanation
Program.cs · Recalculate after changing an input
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Quantity: 4
Subtotal: 4800 cents
The second multiplication reads the updated quantity and assigns the new result. In a smaller program that only needs the final total, you could instead move the initial subtotal declaration below the quantity change. Both approaches put the calculation after its final input is available; neither hardcodes 4800 as an answer.
Independent lab: keep a stock report consistent
Complete a stock report using a fixed starting baseline and a changing cumulative sold count. The purpose is to track assignments and dependent values correctly, not to build a stock-management system.
Acceptance checklist
- Keep StartingStock as a const initialized to 30.
- Start soldItems at 6, then update the same local to a final count of 10.
- After the final update, compute remaining stock from the baseline minus that final count.
- Print exactly Sold: 10 and Remaining: 20 on separate lines.
- Use variable references in the calculation rather than fixed final answers.
- Explain why subtracting final soldItems from an earlier remainingStock double-counts part of the sales.
Program.cs · Stock report starter
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Sold: 10
Remaining: 24
The starter deliberately has a stale derived value. Decide what the final sold count means, then update remainingStock at the appropriate point. StartingStock is a fixed baseline for this exercise; soldItems represents a cumulative count, not an additional sale to subtract a second time.
Show hints
- An assignment to soldItems does not automatically update remainingStock.
- Recompute using StartingStock - soldItems after soldItems changes.
- The final sold count is cumulative, not an extra batch to subtract from the old remaining count.
Reveal the reference solution
Program.cs · Stock report solution
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Sold: 10
Remaining: 20
Recomputing from the original baseline and the final cumulative sold count produces 20. Subtracting the final sold count from the previously calculated remaining stock would count some sales twice. This report assumes counts within the available stock; it does not enforce that range, reserve items or save inventory to a database.
Boundary values and changed inputs
- Final sold count 0 should leave 30; final count 30 should leave 0.
- Final sold count 35 produces -5: the program has not implemented validation.
- Change the baseline to 50 and final sold count to 12; expect 38.
- Change the earlier sold count from 6 to 2 while keeping final count 10. The final remaining value must still be 20.
- Run the program again and explain why its source initializes the locals again rather than loading saved inventory.
Frequently asked questions
Does var mean the type can change later?
No. The compiler infers a fixed compile-time type from the initializer. Assignments afterward must still be compatible with that type.
Why does a local int not simply start at zero?
A local declared without an initializer must be definitely assigned before it is read. Other storage categories have different default-value rules; they do not permit reading an unassigned local.
Why did changing quantity not change the subtotal?
The subtotal holds the result of a calculation that already ran. Assign a new calculated result after the input changes, or calculate only after the final inputs are ready.
Should everything that stays unchanged in one run be const?
No. const requires a supported compile-time constant expression. An ordinary copied starting value or a value obtained at runtime is not automatically a constant just because your current code never reassigns it.
Do variables remember their value after refreshing the lesson?
These programs start a separate execution when run. Their source initializes local values again. Persistent state requires an explicit storage mechanism, which these examples do not have.
Can you trace the current values?
Use the assignment order, inferred types and constant rules to predict the result. Check your answers to see the reasoning.
Recap and next step
A declaration introduces a typed name; initialization supplies its first value. Later assignment evaluates a compatible expression and stores a new value. Integer copies and calculated subtotals retain the values assigned to them until another statement changes them.
var lets the compiler infer a local’s type; it does not remove that type. const names an eligible compile-time value and prevents later reassignment. Next is C# Data Types, where you will choose representations and ranges more deliberately.
Official references
Original SovranCode explanations, scenarios and exercises. Language rules were checked against these references.
- Microsoft Learn: Local declarations and constants
- Microsoft Learn: Assignment operators
- Microsoft Learn: Implicitly typed locals
- Microsoft Learn: Constants
Last updated: .