Branching with if/else
Control flow decides which code runs and how many times it runs. In interactive console apps, you typically branch based on user input, validation results, or computed values.
Basic decision: one condition, two paths
Use if when you want to run a block only when a condition is true. Add else when you need an alternative path.
int age = 17; if (age >= 18) { Console.WriteLine("Adult"); } else { Console.WriteLine("Minor"); }Chaining decisions: multiple conditions
Use else if when you have mutually exclusive conditions. Order matters: the first matching condition wins.
int score = 82; if (score >= 90) { Console.WriteLine("A"); } else if (score >= 80) { Console.WriteLine("B"); } else if (score >= 70) { Console.WriteLine("C"); } else { Console.WriteLine("Needs improvement"); }Guard clauses to keep code readable
When a workflow has invalid states (bad input, unsupported options), handle them early and return/continue. This reduces nested if blocks and keeps the “happy path” clear.
// Example: inside a loop that reads a menu choice string choice = Console.ReadLine() ?? ""; if (choice.Length == 0) { Console.WriteLine("Please enter a choice."); continue; } // Happy path continues here...In console apps, guard clauses are often used with continue (skip to next loop iteration) or return (end the program or method).
Continue in our app.
You can listen to the audiobook with the screen off, receive a free certificate for this course, and also have access to 5,000 other free online courses.
Or continue reading below...Download the app
Multi-way branching with switch
Use switch when you want to select one of many paths based on a single value (often a menu option). It reads cleaner than many else if blocks.
Classic switch for menu commands
string command = (Console.ReadLine() ?? "").Trim().ToLowerInvariant(); switch (command) { case "1": Console.WriteLine("Add"); break; case "2": Console.WriteLine("Subtract"); break; case "x": Console.WriteLine("Exit"); break; default: Console.WriteLine("Unknown option"); break; }Use default as a safety net for unexpected values.
Pattern-friendly cases (when appropriate)
Modern C# supports pattern matching in switch. This is useful when you want to branch based on ranges or additional conditions without deeply nested if statements.
int temperature = 28; string label = temperature switch { <= 0 => "Freezing", < 15 => "Cold", < 25 => "Mild", < 35 => "Warm", _ => "Hot" }; Console.WriteLine(label);You can also add conditions with when:
int hours = 22; string message = hours switch { int h when h >= 0 && h < 6 => "Late night", int h when h >= 6 && h < 12 => "Morning", int h when h >= 12 && h < 18 => "Afternoon", _ => "Evening" }; Console.WriteLine(message);Loops: repetition for interactive workflows
Loops let you repeat a block of code. In interactive apps, loops commonly power menus, repeated prompts, and “keep asking until valid” input patterns.
while: repeat while a condition is true
while checks the condition before each iteration. It’s ideal for input-driven loops where you don’t know how many times the user will repeat an action.
string? line = Console.ReadLine(); while (line != "exit") { Console.WriteLine($"You typed: {line}"); line = Console.ReadLine(); }Sentinel values to exit
A sentinel value is a special input that signals “stop.” Common examples: x, q, exit, or 0. Design your prompts so the sentinel is obvious.
while (true) { Console.Write("Enter a number (or x to stop): "); string input = (Console.ReadLine() ?? "").Trim(); if (input.Equals("x", StringComparison.OrdinalIgnoreCase)) break; if (!double.TryParse(input, out double value)) { Console.WriteLine("Not a valid number."); continue; } Console.WriteLine($"Squared: {value * value}"); }do/while: run at least once
do/while is useful when you must execute the body at least once, such as showing a menu before checking whether the user wants to exit.
string choice; do { Console.WriteLine("1) Say hello"); Console.WriteLine("x) Exit"); Console.Write("Choice: "); choice = (Console.ReadLine() ?? "").Trim().ToLowerInvariant(); if (choice == "1") Console.WriteLine("Hello!"); else if (choice != "x") Console.WriteLine("Unknown option"); } while (choice != "x");for: repeat a known number of times
for is best when you know the number of iterations, such as repeating a prompt a fixed number of attempts or processing indices.
for (int attempt = 1; attempt <= 3; attempt++) { Console.WriteLine($"Attempt {attempt} of 3"); }foreach: iterate through a sequence
foreach is the cleanest way to iterate through items in a collection. In console apps, it’s often used to print menu options, list results, or process a set of values.
string[] options = { "1) Add", "2) Subtract", "x) Exit" }; foreach (string opt in options) { Console.WriteLine(opt); }Building an input-driven menu loop (step-by-step)
A common interactive workflow is a menu that keeps running until the user chooses to exit. The core pattern is: show menu, read choice, validate, branch, repeat.
Step 1: Create the loop and sentinel exit
while (true) { Console.WriteLine("=== Menu ==="); Console.WriteLine("1) Option A"); Console.WriteLine("2) Option B"); Console.WriteLine("x) Exit"); Console.Write("Select: "); string choice = (Console.ReadLine() ?? "").Trim().ToLowerInvariant(); if (choice == "x") break; Console.WriteLine("(work happens here)"); }Step 2: Add a switch for clear branching
while (true) { Console.WriteLine("=== Menu ==="); Console.WriteLine("1) Option A"); Console.WriteLine("2) Option B"); Console.WriteLine("x) Exit"); Console.Write("Select: "); string choice = (Console.ReadLine() ?? "").Trim().ToLowerInvariant(); if (choice == "x") break; switch (choice) { case "1": Console.WriteLine("You chose A"); break; case "2": Console.WriteLine("You chose B"); break; default: Console.WriteLine("Unknown option. Try again."); break; } }Step 3: Use guard clauses for input validation inside options
When an option requires additional input (like numbers), validate early and continue to keep the main flow readable.
Console.Write("Enter amount: "); string raw = (Console.ReadLine() ?? "").Trim(); if (!double.TryParse(raw, out double amount)) { Console.WriteLine("Invalid number."); continue; } // Use amount safely hereExercise: Menu-based calculator (keeps running until exit)
Goal: Build a calculator that repeatedly shows a menu, performs the chosen operation, and returns to the menu until the user exits.
Required behavior
- Menu options: Add, Subtract, Multiply, Divide, Exit.
- After each operation, show the result and return to the menu.
- Use sentinel value (menu option
xor0) to exit. - Use guard clauses for invalid menu choices and invalid numeric input.
- Handle division by zero with a clear message.
Suggested implementation (one-file console program)
while (true) { Console.WriteLine("=== Calculator ==="); Console.WriteLine("1) Add"); Console.WriteLine("2) Subtract"); Console.WriteLine("3) Multiply"); Console.WriteLine("4) Divide"); Console.WriteLine("x) Exit"); Console.Write("Choice: "); string choice = (Console.ReadLine() ?? "").Trim().ToLowerInvariant(); if (choice == "x") break; if (choice != "1" && choice != "2" && choice != "3" && choice != "4") { Console.WriteLine("Unknown option."); continue; } Console.Write("Enter first number: "); string aRaw = (Console.ReadLine() ?? "").Trim(); if (!double.TryParse(aRaw, out double a)) { Console.WriteLine("Invalid number."); continue; } Console.Write("Enter second number: "); string bRaw = (Console.ReadLine() ?? "").Trim(); if (!double.TryParse(bRaw, out double b)) { Console.WriteLine("Invalid number."); continue; } switch (choice) { case "1": Console.WriteLine($"Result: {a + b}"); break; case "2": Console.WriteLine($"Result: {a - b}"); break; case "3": Console.WriteLine($"Result: {a * b}"); break; case "4": if (b == 0) { Console.WriteLine("Cannot divide by zero."); break; } Console.WriteLine($"Result: {a / b}"); break; }Extension ideas: allow repeated operations without returning to the main menu, support rounding, or add a history list printed with foreach.
Exercise alternative: Unit converter with a running menu
Build a converter that loops until exit. Include at least two conversion categories and validate inputs.
Example menu requirements
- 1) Celsius to Fahrenheit
- 2) Fahrenheit to Celsius
- 3) Kilometers to Miles
- 4) Miles to Kilometers
- x) Exit
Implementation sketch (focus on control flow)
while (true) { Console.WriteLine("=== Unit Converter ==="); Console.WriteLine("1) C -> F"); Console.WriteLine("2) F -> C"); Console.WriteLine("3) km -> mi"); Console.WriteLine("4) mi -> km"); Console.WriteLine("x) Exit"); Console.Write("Choice: "); string choice = (Console.ReadLine() ?? "").Trim().ToLowerInvariant(); if (choice == "x") break; if (choice != "1" && choice != "2" && choice != "3" && choice != "4") { Console.WriteLine("Unknown option."); continue; } Console.Write("Enter value: "); string raw = (Console.ReadLine() ?? "").Trim(); if (!double.TryParse(raw, out double v)) { Console.WriteLine("Invalid number."); continue; } double result = choice switch { "1" => (v * 9.0 / 5.0) + 32.0, "2" => (v - 32.0) * 5.0 / 9.0, "3" => v * 0.621371, "4" => v / 0.621371, _ => 0.0 }; Console.WriteLine($"Result: {result}"); }