User Input (Console.ReadLine)
Reviewed & published by Brayan K
So far your programs have done all the talking. Now they'll listen. Console.ReadLine() lets a person type an answer, turning a static script into an interactive program. The catch — and the whole skill of this lesson — is that input always arrives as text, so you must convert and validate it before you can trust it.
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
- Read text from the keyboard with Console.ReadLine
- Write prompts with Console.Write (no newline)
- Convert input to numbers safely with TryParse
- Read several values to build a small form
- Validate input in a re-prompt loop
- Handle the empty / null input case
💡 Real-World Analogy
Reading input is like a receptionist taking a message. They write down exactly what you say, word for word, as plain text on a sticky note — they don't interpret "thirty" as the number 30 or decide whether "yes" means true. That translation is your job afterwards. ReadLine() is that sticky note: faithful text, no interpretation. You decide what it means.
1. Reading Text
The pattern is two lines: a Console.Write to ask the question (it stays on the same line so the answer sits next to it), then Console.ReadLine() to capture what the user types up to the Enter key. The result is a string you can use immediately.
using System;
class Program
{
static void Main()
{
// Console.Write prints a prompt WITHOUT a newline so the
// answer appears on the same line as the question.
Console.Write("What's your name? ");
// Console.ReadLine reads everything the user types until Enter,
// and hands it back as a STRING.
string name = Console.ReadLine();
Console.WriteLine($"Hello, {name}! Nice to meet you.");
// If the input is "Brenda", the output is:
// What's your name? Brenda
// Hello, Brenda! Nice to meet you.
}
}2. Reading Numbers
Because input is always text, doing maths with it requires a conversion. Wrapping ReadLine() in int.TryParse gives you a number and protects you from a crash if the user types something silly. This is the single most common real-world input pattern.
using System;
class Program
{
static void Main()
{
// ReadLine ALWAYS gives text, so to do maths we must convert.
Console.Write("Enter your age: ");
string ageText = Console.ReadLine();
// The SAFE way: TryParse returns false instead of crashing.
if (int.TryParse(ageText, out int age))
{
int nextYear = age + 1;
Console.WriteLine($"Next year you'll be {nextYear}.");
}
else
{
Console.WriteLine("That wasn't a whole number!");
}
// For "30" the output is:
// Enter your age: 30
// Next year you'll be 31.
}
}Your turn. Build a tiny tip calculator. The bill is read for you as text — convert it to a decimal and the rest will work.
using System;
class Program
{
static void Main()
{
// 🎯 YOUR TURN — build a tiny tip calculator from user input.
Console.Write("Bill total: ");
string billText = Console.ReadLine();
// 1) Convert billText to a decimal (hint: decimal.Parse)
decimal bill = ___; // 👉 decimal.Parse(billText)
// 2) Compute a 15% tip
decimal tip = bill * 0.15m;
// 3) Print the tip and grand total, both as currency (:C)
Console.WriteLine($"Tip: {tip:C}, Total: {bill + tip:C}");
// ✅ For a bill of "40": Tip: £6.00, Total: £46.00
}
}3. Several Inputs in a Row
Most programs ask more than one question. You simply repeat the prompt-and-read pattern, storing each answer in its own variable. Notice you can convert inline — int.TryParse(Console.ReadLine(), out int year) reads and parses in a single step.
using System;
class Program
{
static void Main()
{
// Read several values in a row to build a small profile.
Console.Write("First name: ");
string first = Console.ReadLine();
Console.Write("Last name: ");
string last = Console.ReadLine();
Console.Write("Birth year: ");
int.TryParse(Console.ReadLine(), out int birthYear);
int age = 2026 - birthYear;
Console.WriteLine();
Console.WriteLine($"Full name: {first} {last}");
Console.WriteLine($"Age in 2026: {age}");
// Input: Ada / Lovelace / 1990
// Output:
// Full name: Ada Lovelace
// Age in 2026: 36
}
}🔎 Deep Dive: validating with a loop
Real apps don't give up after one bad answer — they ask again. The standard recipe is a while loop that only breaks once the input passes every check. Combine TryParse with a range check (quantity > 0) so both "abc" and "-5" get politely rejected.
using System;
class Program
{
static void Main()
{
// A real pattern: keep asking until the input is valid.
int quantity;
while (true)
{
Console.Write("How many tickets? ");
string input = Console.ReadLine();
if (int.TryParse(input, out quantity) && quantity > 0)
break; // good input — leave the loop
Console.WriteLine("Please enter a positive whole number.");
}
Console.WriteLine($"Booking {quantity} ticket(s). Thanks!");
// Bad inputs are re-prompted; only a positive int gets through.
}
}One more thing to know: when there's no more input, ReadLine() returns null, not an empty string. With nullable reference types on, its type is string?, so guard with if (input is null) ... before using it in a fully robust program.
🧩 Reorder Challenge
These five lines ask for a number and greet the user. Order them so the program prompts, reads, converts, and then prints You entered 8 for an input of 8.
Console.WriteLine($"You entered {value}");
string text = Console.ReadLine();
Console.Write("Enter a number: ");
int.TryParse(text, out int value);
// (these four lines go inside Main)Console.Write("Enter a number: ");
string text = Console.ReadLine();
int.TryParse(text, out int value);
Console.WriteLine($"You entered {value}");Why: you must show the prompt before reading, read into text before parsing it, declare value via the TryParse out before using it, and print last. Each line depends on the variable created by the line above it.
🧠 Quick Recall
1. If the user types 5, what prints?
string s = Console.ReadLine();
Console.WriteLine(s + 3);53 — s is the string "5", and "5" + 3 concatenates to "53". You meant to parse it to a number first.
2. What's the difference in output position?
Console.Write("A");
Console.Write("B");AB on one line — Write does not add a newline, so the two stay together. WriteLine would have split them across lines.
3. User types cat. What prints?
bool ok = int.TryParse(Console.ReadLine(), out int n);
Console.WriteLine($"{ok}/{n}");False/0 — "cat" can't parse, so ok is false and n stays at its default 0.
Pro Tips
- 💡 Use Console.Write for prompts so the answer sits on the same line as the question.
- 💡 Never do maths on raw input. Convert with TryParse first — "5" + 3 is "53", not 8.
- 💡 Validate in a loop for anything important, re-prompting until the input is acceptable.
- 💡 Trim if needed: Console.ReadLine().Trim() removes stray spaces a user might add.
Common Errors (and the fix)
- String concatenation instead of addition: reading "5" and writing s + 3 gives "53". Parse to int before adding.
- Crash on letters: int.Parse(Console.ReadLine()) throws if the user types text. Use TryParse.
- NullReferenceException: at end-of-input ReadLine() returns null. Guard before calling methods like .Trim() on it.
- Prompt on its own line: using WriteLine for the prompt pushes the cursor down. Use Write to keep the answer beside the question.
Mini-Challenge: Registration Form
Ask for a name and a favourite number, validate the number with TryParse, and respond accordingly. The outline is in the comments — fill in the body.
using System;
class Program
{
static void Main()
{
// 🎯 MINI-CHALLENGE: Simple registration form
// 1. Ask for the user's name (Console.Write + ReadLine).
// 2. Ask for their favourite number; convert with int.TryParse.
// 3. If the number is valid, print:
// "Hi <name>! Double your number is <n*2>."
// Otherwise print "That wasn't a number, <name>."
//
// ✅ Example run:
// Name: Sam
// Favourite number: 7
// Hi Sam! Double your number is 14.
// your code here
}
}🎉 Lesson Complete
- ✅ Console.ReadLine() reads a line of text the user types
- ✅ Console.Write shows a prompt on the same line; WriteLine adds a newline
- ✅ Input is always a string — convert with TryParse before doing maths
- ✅ Read several values in sequence to build a form
- ✅ Validate with a while loop that re-prompts until the input is good
Practice quiz
What type does Console.ReadLine() return for the text a user types?
- int
- object
- string
- char
Answer: string. Console input is plain text, so ReadLine hands it back as a string. You must convert it yourself if you need a number.
Why use Console.Write rather than Console.WriteLine for a prompt?
- Write leaves the cursor on the same line so the answer sits beside the question
- Write is faster
- WriteLine cannot print text
- Write automatically reads input
Answer: Write leaves the cursor on the same line so the answer sits beside the question. Console.Write prints without a trailing newline, so the user's typed answer appears on the same line as the prompt.
If a user types 5 and you run Console.WriteLine(Console.ReadLine() + 3), what prints?
- 8
- 35
- A compile error
- 53
Answer: 53. ReadLine returns the string "5", and "5" + 3 concatenates to "53". You must parse the text to an int before doing arithmetic.
What is the safest way to turn user input into an int?
- int.Parse(Console.ReadLine())
- int.TryParse(Console.ReadLine(), out int n)
- (int)Console.ReadLine()
- Convert.ToChar(Console.ReadLine())
Answer: int.TryParse(Console.ReadLine(), out int n). int.TryParse returns false on bad input instead of throwing, letting you re-prompt or show a friendly message rather than crashing.
A user types "cat" into int.TryParse(input, out int n). What are the results?
- returns false, n is 0
- returns true, n is 0
- returns false, n is -1
- throws a FormatException
Answer: returns false, n is 0. "cat" cannot be parsed, so TryParse returns false and sets the out variable n to its default value, 0.
What does int.Parse(Console.ReadLine()) do if the user types letters?
- Returns 0
- Returns null
- Throws an exception
- Returns the first letter as a number
Answer: Throws an exception. Parse throws a FormatException on non-numeric text, crashing the program. TryParse is the safe alternative.
At end of input (the stream is closed), what does Console.ReadLine() return?
- An empty string
- null
- A space character
- Zero
Answer: null. When there is no more input, ReadLine returns null rather than an empty string, which is why its type is string? with nullable reference types on.
What is the standard pattern to keep asking until the input is valid?
- A for loop counting to 10
- A try/catch with no loop
- Recursion with Console.Write
- A while loop that only breaks once the input passes every check
Answer: A while loop that only breaks once the input passes every check. The common recipe is a while loop that re-prompts and only breaks when TryParse succeeds and any range check (e.g. quantity > 0) passes.
Why guard for null before calling Console.ReadLine().Trim()?
- Trim is slow
- ReadLine can return null at end of input, so calling .Trim() on it throws a NullReferenceException
- Trim only works on numbers
- Trim removes the newline
Answer: ReadLine can return null at end of input, so calling .Trim() on it throws a NullReferenceException. Since ReadLine can return null when input ends, calling a method like .Trim() on a null reference throws a NullReferenceException unless you guard first.
Which type is best for reading a money value like a bill total?
- int via int.Parse
- char via Convert.ToChar
- decimal via decimal.Parse / decimal.TryParse
- bool via bool.Parse
Answer: decimal via decimal.Parse / decimal.TryParse. Currency needs fractional precision without binary rounding error, so decimal (parsed with decimal.Parse or decimal.TryParse) is the right choice.
Continue this course
- Previous: Type Casting & Boxing
- Next: Strings, Interpolation & StringBuilder — String methods, $"interpolation", and efficient StringBuilder
- Quick reference: C# cheat sheet
Frequently asked questions
Why does Console.ReadLine always return a string?
Console input is just text typed at the keyboard, so the runtime hands it back as a string. If you need a number you must convert it yourself with int.Parse or, better, int.TryParse. There is no way for ReadLine to know whether you wanted a number or text.
What is the difference between Console.Write and Console.WriteLine?
Console.Write prints text and leaves the cursor on the same line, which is perfect for a prompt like 'Enter your name: '. Console.WriteLine prints the text and then moves to a new line. Using Write for prompts keeps the user's typed answer on the same line as the question.
How do I read a number safely from the console?
Read the line as a string, then call int.TryParse (or decimal.TryParse for money). TryParse returns false on bad input instead of throwing, so you can re-prompt or show a friendly message rather than crashing the program with an unhandled exception.
What does Console.ReadLine return at end of input?
If the input stream is closed or there is no more input, ReadLine returns null rather than an empty string. In modern C# with nullable reference types enabled this is why the return type is string?, and it is good practice to handle the null case before using the value.