User Input & Output
Console I/O is the fastest way to prototype logic; production systems use structured logging, HTTP, and message buses.
Introduction
Console I/O is the fastest way to prototype logic; production systems use structured logging, HTTP, and message buses. Still, mastering Console, TextReader/Writer, and culture-aware formatting builds foundations for CLI tools and interview stdin/stdout problems.
Enterprise apps prefer ILogger over Console.WriteLine, but parsing user input with TryParse, validating ranges, and formatting currency with CultureInfo appear daily in banking terminals and healthcare kiosks.
This lesson covers ReadLine, WriteLine, string interpolation, composite formatting, and safe parsing patterns that prevent unhandled FormatException in production.
The story
A bank teller kiosk asks customers to type a deposit amount on a touchscreen. The app reads input from the console (or a simulated input stream in tests), validates that the value is a positive number, and prints a formatted confirmation like Accepted deposit: $250.00.
Separating input and output into TextReader and TextWriter lets QA automate the same logic without a human at the keyboard — a pattern used daily in enterprise testing.
Understanding the topic
Key concepts
- Console.In/Out/Error map to standard streams for CLI integration.
- ReadLine returns string? — null on EOF; always validate.
- int.TryParse, decimal.TryParse avoid exception-based control flow.
- String interpolation ($"value {expr}") calls ToString on expressions.
- CultureInfo.InvariantCulture for machine-readable logs; CurrentCulture for UI.
- StringBuilder for efficient large string assembly.
sequenceDiagramUser->>Console: ReadLine()Console->>App: string inputApp->>App: Parse & ValidateApp->>Console: WriteLine(result)
Step-by-step explanation
- Prompt user with Console.Write (no newline) or WriteLine.
- ReadLine blocks until Enter; trim whitespace before parse.
- TryParse returns bool and out parameter with parsed value.
- Format numbers: value.ToString('C', culture) for currency.
- Redirect input/output in tests via StringReader/StringWriter.
- Async console APIs available but rarely used — prefer async streams for files/network.
Practical code example
Interactive deposit CLI with TryParse and invariant culture logging:
namespace TechLearningPro.IO;public static class DepositCli{public static void Run(TextReader input, TextWriter output){output.WriteLine("Enter deposit amount (USD):");var line = input.ReadLine();if (!decimal.TryParse(line, NumberStyles.Number, CultureInfo.InvariantCulture, out var amount)|| amount <= 0){output.WriteLine("Invalid amount. Use format: 123.45");return;}output.WriteLine(CultureInfo.InvariantCulture, quot;Accepted deposit: {amount:C}");}}
Output
Enter deposit amount (USD): Accepted deposit: $250.00
Line-by-line code explanation
Run(TextReader input, TextWriter output)accepts abstract streams so unit tests can inject fake readers/writers.output.WriteLine("Enter deposit amount...")prompts the user before reading input.input.ReadLine()reads one line of text typed by the user (or supplied by a test).decimal.TryParse(line, NumberStyles.Number, CultureInfo.InvariantCulture, out var amount)safely parses numbers independent of regional settings.|| amount <= 0rejects zero and negative deposits in the same condition.output.WriteLine("Invalid amount...")gives actionable feedback when parsing fails.returnexits early without processing invalid input further.output.WriteLine(..., $"Accepted deposit: {amount:C}")formats the accepted amount as currency using invariant culture.
Key takeaway: Inject TextReader/TextWriter for unit testing without real console. InvariantCulture keeps logs consistent across regions.
Real-world use
Where you'll use this in production
- DevOps CLI tools accepting parameters interactively or from pipes.
- Healthcare kiosk weight entry with validation and localized display.
- Coding interview stdin/stdout judge problems.
- Migration scripts prompting for connection string confirmation.
Best practices
- Always use TryParse for user/external input.
- Separate display culture from storage format (ISO 8601, invariant decimals).
- Write errors to Console.Error or ILogger LogError.
- Avoid ReadLine in ASP.NET — use model binding instead.
- Use StringBuilder for >3 concatenations in loops.
Common mistakes
- Parse without TryParse — crashes on bad input.
- Concatenating culture-specific strings in persisted logs.
- Assuming ReadLine never returns null.
- Using + in tight loops for string building.
Advanced interview questions
Q1BeginnerHow read user input safely?
Q2BeginnerPurpose of StringBuilder?
Q3IntermediateInvariantCulture vs CurrentCulture?
Q4IntermediateTest console apps without manual typing?
Q5AdvancedDesign a CLI that works in CI (non-interactive) and locally (interactive).
Summary
Console I/O uses standard streams; validate all external input. TryParse and culture-aware formatting prevent runtime format errors. Inject abstractions for testable CLI logic. Production web apps use model binding and ILogger instead of Console. Next: if/else and boolean decision logic.