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

💡 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

Common Errors (and the fix)

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

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

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.