Variables & Data Types
Reviewed & published by Brayan K
By the end of this lesson you'll be able to store text, numbers, and true/false values in C#, convert safely between them, and print them in clean, formatted output — the foundation of every C# program you'll ever write.
Part of the free C# course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
What You'll Learn
- Declare variables with the right type (int, string, double, bool, char)
- Understand why C# is strongly typed (and why that helps you)
- Convert between types with casting, Parse, and TryParse
- Use decimal for money and know why double is wrong for it
- Format output with string interpolation (:C, :F2, :P1)
- Use var and const correctly
💡 Real-World Analogy
A variable is a labelled container in a kitchen. A jar labelled "Sugar" (string) holds text; a measuring cup labelled "Cups" (int) holds whole numbers; a scale labelled "Weight" (double) holds decimals. Each container only holds one kind of thing — you can't pour flour into a liquid measuring cup. C#'s type system works exactly like that: every variable has a type that fixes what it can store. That strictness is a feature — it catches mistakes before your program runs.
📊 The Core Data Types
| Type | Holds | Example | When to use |
|---|---|---|---|
| int | Whole numbers | int age = 25; | Counts, ages, indexes |
| double | Decimal numbers | double h = 1.75; | Measurements, averages |
| decimal | Exact decimals | decimal p = 9.99m; | Money & finance |
| string | Text | string n = "Al"; | Names, messages, input |
| char | One character | char g = 'A'; | A single letter/symbol |
| bool | true / false | bool ok = true; | Yes/no decisions |
Notice string uses "double quotes" but char uses 'single quotes' — mixing these up is the #1 beginner error, so it's worth burning in now.
1. Declaring Variables
Every variable needs a type and a name, and you usually give it a value in the same line: type name = value;. Use descriptive camelCase names like firstName or totalPrice — code is read far more often than it's written, so a clear name pays for itself. Read this worked example first, run it, then you'll write your own.
using System;
class Program
{
static void Main()
{
// A variable = a named box that stores ONE type of value.
// Pattern: type name = value;
string name = "Alice"; // text -> always in "double quotes"
int age = 25; // whole number (no decimal point)
double height = 5.7; // decimal number
bool isStudent = true; // true or false (lowercase in C#)
char grade = 'A'; // a SINGLE character -> 'single quotes'
// $"..." is string interpolation: {name} is replaced by the value.
Console.WriteLine($"Name: {name}"); // Name: Alice
Console.WriteLine($"Age: {age}"); // Age: 25
Console.WriteLine($"Height: {height}ft"); // Height: 5.7ft
Console.WriteLine($"Student: {isStudent}");// Student: True
Console.WriteLine($"Grade: {grade}"); // Grade: A
}
}
// ✅ Expected output:
// Name: Alice
// Age: 25
// Height: 5.7ft
// Student: True
// Grade: AYour turn. The program below is almost complete — fill in the three blanks marked ___ using the hints in the comments, then run it.
using System;
class Program
{
static void Main()
{
// 🎯 YOUR TURN — replace each ___ then press "Try it Yourself".
// 1) Make an int called "year" set to the current year
int year = ___; // 👉 a whole number, e.g. 2026
// 2) Make a string called "city" set to a city name
string city = ___; // 👉 text in "double quotes"
// 3) Make a double called "price" set to 9.99
double price = ___; // 👉 a decimal number
// These lines already work once your variables exist:
Console.WriteLine($"In {year}, a coffee in {city} costs £{price}");
// ✅ Expected output (example):
// In 2026, a coffee in London costs £9.99
}
}2. Type Casting & Conversion
Sometimes a value is the wrong type and you need to convert it. Implicit casting happens automatically when it's safe (an int fits inside a double). Explicit casting with (type) is you saying "I accept I might lose data". Converting text to numbers is the most common case — and the place beginners' programs crash — so we use the safe TryParse for anything that came from a user.
using System;
class Program
{
static void Main()
{
// Implicit casting — automatic and SAFE (no data is lost).
int myInt = 100;
double myDouble = myInt; // int -> double happens for you
Console.WriteLine($"int: {myInt}, double: {myDouble}"); // 100, 100
// Explicit casting — you ask for it with (type), and it MAY lose data.
double pi = 3.14159;
int rounded = (int)pi; // 3 (the .14159 is dropped, not rounded)
Console.WriteLine($"double: {pi}, int: {rounded}");
// Strings -> numbers. int.Parse throws if the text isn't a number.
string ageStr = "25";
int parsedAge = int.Parse(ageStr); // 25
Console.WriteLine($"Parsed age: {parsedAge}");
// TryParse is the SAFE version — it returns false instead of crashing.
string input = "abc";
if (int.TryParse(input, out int result))
Console.WriteLine($"Parsed: {result}");
else
Console.WriteLine($"'{input}' is not a valid number"); // this runs
}
}
// ✅ Expected output:
// int: 100, double: 100
// double: 3.14159, int: 3
// Parsed age: 25
// 'abc' is not a valid numberNow you try. Input from a user always arrives as string text, so before you can do maths you must convert it. Fill in the two blanks:
using System;
class Program
{
static void Main()
{
// 🎯 YOUR TURN — input() always gives TEXT, so we must convert it.
string quantityText = "3";
string priceText = "4.50";
// 1) Convert quantityText to an int (hint: int.Parse(...))
int quantity = ___; // 👉 int.Parse(quantityText)
// 2) Convert priceText to a double (hint: double.Parse(...))
double unitPrice = ___; // 👉 double.Parse(priceText)
double total = quantity * unitPrice;
Console.WriteLine($"{quantity} items x £{unitPrice} = £{total:F2}");
// ✅ Expected output: 3 items x £4.5 = £13.50
}
}3. String Interpolation & Formatting
String interpolation — the $"..." syntax — lets you drop variables straight into text inside {curly braces}. It reads far better than gluing strings together with +. After a colon you can add a format specifier: :C for currency, :F2 for 2 decimal places, :P1 for a percentage. Use @"..." for file paths so you don't have to escape every backslash.
using System.Globalization;
using System;
class Program
{
static void Main()
{
// Currency formatting follows the thread's culture: {value:C} prints
// £ in London, $ in Boston and € in Paris. Pin it when the output has
// to be the same everywhere — as it does on a page that shows you the
// result.
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en-GB");
string name = "John";
int age = 30;
decimal salary = 55000.75m; // the 'm' suffix means decimal
// Old way: string concatenation with +
Console.WriteLine("Name: " + name + ", Age: " + age);
// Modern way: string interpolation with $"..."
Console.WriteLine($"Name: {name}, Age: {age}");
// Format specifiers live after a colon inside the braces:
Console.WriteLine($"Salary: {salary:C}"); // £55,000.75 (Currency)
Console.WriteLine($"Pi: {Math.PI:F4}"); // 3.1416 (4 decimals)
Console.WriteLine($"Done: {0.856:P1}"); // 85.6% (Percent)
// Verbatim string @"..." — backslashes are literal (great for paths).
string path = @"C:\Users\John\Documents";
Console.WriteLine(path); // C:\Users\John\Documents
}
}
// ✅ Expected output:
// Name: John, Age: 30
// Name: John, Age: 30
// Salary: £55,000.75
// Pi: 3.1416
// Done: 85.6%
// C:\Users\John\Documents🔎 Deep Dive: var and const
var lets the compiler figure out the type from the value: var city = "London"; is exactly the same as string city = "London";. It's fine when the type is obvious from the right-hand side, but avoid it when it isn't (var data = GetData(); hides what you're dealing with).
const marks a value that must never change after it's set, and the compiler enforces it: const double Pi = 3.14159;. Constants are written in PascalCase by convention and make your intent obvious to the next developer (often future‑you).
var greeting = "Hi"; // compiler infers string
const int MaxLives = 3; // can never be reassigned
// MaxLives = 5; // ❌ compile error: cannot assign to constPutting It Together: a Receipt Calculator
Here's a small but real program that uses everything from this lesson — types, const, arithmetic, and currency formatting. Read it line by line; you understand every part now.
using System.Globalization;
using System;
class Program
{
static void Main()
{
// Currency formatting follows the thread's culture: {value:C} prints
// £ in London, $ in Boston and € in Paris. Pin it when the output has
// to be the same everywhere — as it does on a page that shows you the
// result.
CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en-GB");
// === Receipt calculator — every line uses this lesson's skills ===
string item = "C# Handbook"; // string
decimal price = 24.99m; // decimal -> money (precise)
int quantity = 2; // int
const decimal TAX_RATE = 0.20m; // const -> a value that never changes
decimal subtotal = price * quantity; // 49.98
decimal tax = subtotal * TAX_RATE; // 9.996
decimal total = subtotal + tax; // 59.976
// :C formats as currency; the runtime rounds 59.976 -> £59.98
Console.WriteLine($"Item: {item}");
Console.WriteLine($"Qty: {quantity} @ {price:C}");
Console.WriteLine($"Subtotal: {subtotal:C}");
Console.WriteLine($"Tax(20%): {tax:C}");
Console.WriteLine($"TOTAL: {total:C}");
}
}
// ✅ Expected output:
// Item: C# Handbook
// Qty: 2 @ £24.99
// Subtotal: £49.98
// Tax(20%): £10.00
// TOTAL: £59.98Why decimal and not double for money? Because double stores values in binary and can't represent amounts like 0.1 exactly, so totals drift by tiny fractions of a penny. decimal is built for exact base‑10 money maths.
Pro Tips
- 💡 Use decimal for money, not double: decimal price = 19.99m; is exact; double has rounding drift.
- 💡 Prefer TryParse over Parse for anything a user typed: Parse("abc") throws; TryParse returns false safely.
- 💡 Use var only when the type is obvious from the right-hand side. Clarity beats cleverness.
- 💡 Name things well: totalPrice tells a story; tp or x doesn't.
Common Errors (and the fix)
- "CS0029: Cannot implicitly convert 'double' to 'int'" — you put a decimal in an int. Use double, or cast explicitly with (int) (accepting the lost decimals).
- Forgetting the m on decimals: decimal price = 19.99; won't compile. Write 19.99m.
- Integer division surprise: int r = 7 / 2; gives 3, not 3.5. Cast first: (double)7 / 2.
- Wrong quotes: 'hello' is invalid — strings use "double quotes". Single quotes are only for a single char like 'A'.
- "CS0165: Use of unassigned local variable": you must give a local variable a value before you read it. int x; Console.WriteLine(x); won't compile.
📋 Quick Reference
| Task | Code | Result |
|---|---|---|
| Text → int | int.Parse("42") | 42 |
| Text → int (safe) | int.TryParse(s, out int n) | true / false |
| double → int | (int)3.9 | 3 (truncates) |
| Currency | $"{p:C}" | £9.99 |
| 2 decimals | $"{x:F2}" | 3.14 |
| Percent | $"{r:P1}" | 85.6% |
Frequently Asked Questions
Q: When do I use double vs decimal?
Use decimal for money and anything that must be exact. Use double for scientific or measurement values where tiny rounding is fine and speed matters.
Q: Is var a different "loose" type like in JavaScript?
No. C#'s var is still strongly typed — the compiler picks one fixed type at compile time. var x = 5; makes x an int forever; you can't later assign text to it.
Q: Why did 7 / 2 give me 3?
Both numbers are int, so C# does integer division and drops the remainder. Make one of them a decimal: 7.0 / 2 or (double)7 / 2 → 3.5.
Q: What's the difference between "A" and 'A'?
"A" (double quotes) is a string of length 1. 'A' (single quotes) is a char — a single character. They're different types.
Mini-Challenge: Profile Card
No blanks this time — just a brief and a blank canvas (with an outline to keep you on track). Build it, run it, and check your output against the example in the comments. This is exactly the kind of small program real apps are made of.
using System;
class Program
{
static void Main()
{
// 🎯 MINI-CHALLENGE: Profile card
// 1. Create variables: name (string), age (int),
// heightMeters (double), likesCoding (bool).
// 2. Print a tidy 4-line profile using $"..." interpolation.
// 3. BONUS: it's their birthday — add 1 to age with age += 1;
// then print "Next year you'll be {age}".
//
// ✅ Example output:
// Name: Sam
// Age: 20
// Height: 1.8m
// Likes coding: True
// Next year you'll be 21
// your code here
}
}🎉 Lesson Complete
- ✅ Variables have a fixed type: int, double, decimal, string, char, bool
- ✅ "double quotes" for strings, 'single quotes' for a single char
- ✅ Implicit casting is automatic & safe; explicit (type) casting may lose data
- ✅ TryParse is safer than Parse for user input
- ✅ Interpolation $"{x:F2}" with :C, :F2, :P1 formats output cleanly
- ✅ decimal for money, const for values that never change
Practice quiz
Which type should you use to store money exactly?
- double
- float
- decimal
- int
Answer: decimal. decimal is built for exact base-10 maths, so it's the right choice for money. double has binary rounding drift.
What is the value of an int result from 7 / 2 in C#?
- 3.5
- 3
- 4
- 3.0
Answer: 3. Both operands are int, so C# does integer division and drops the remainder, giving 3.
Which is the correct way to declare a char?
- char g = "A";
- char g = 'A';
- char g = A;
- char g = `A`;
Answer: char g = 'A';. A char uses single quotes: 'A'. Double quotes make a string instead.
What suffix marks a decimal literal?
- d
- f
- m
- c
Answer: m. The m suffix makes a literal a decimal, e.g. 19.99m. Without it the literal is a double.
Which is safer for converting user input text to a number?
- int.Parse
- int.TryParse
- (int) cast
- Convert.ToString
Answer: int.TryParse. int.TryParse returns false instead of throwing when the text isn't a valid number.
What does var x = 5; make x?
- A loosely typed value like in JavaScript
- A string
- An int fixed at compile time
- A double
Answer: An int fixed at compile time. var is still strongly typed; the compiler infers int from 5, and x stays an int.
Explicit casting with (int) on 3.9 gives what?
- 4
- 3
- 3.9
- An error
Answer: 3. Casting a double to int truncates (drops the decimals), so (int)3.9 is 3 — it does not round.
Which keyword marks a value that can never change after it is set?
- static
- readonly
- const
- final
Answer: const. const marks a compile-time constant the compiler won't let you reassign.
What does the format specifier :C produce, as in $"{p:C}"?
- A percentage
- Currency formatting
- Two decimal places
- Scientific notation
Answer: Currency formatting. :C formats the value as currency, e.g. £9.99.
Going from int to double (e.g. double d = myInt;) is an example of what?
- Explicit casting
- Implicit casting
- Parsing
- A compile error
Answer: Implicit casting. An int fits safely inside a double, so C# converts it implicitly with no data loss.
Continue this course
- Previous: Introduction to C#
- Next: Data Types — Value vs reference types, ranges, and choosing the right type
- Quick reference: C# cheat sheet › Basics