C# Input and Output

Build interactive console programs: read what users type with Console.ReadLine, handle empty input and nulls, convert text to numbers safely, keep asking until input is valid, and format output clearly.

Lesson 5 of 43Beginner18 min read

A program becomes much more interesting when it responds to the person using it. Console programs talk to users through the terminal: they print a prompt, read what the user types, and print a result. Many real tools work this way, from dotnet and git to small scripts that automate work.

In C#, Console.WriteLine and Console.Write handle output, and Console.ReadLine reads a whole line of input as a string. The tricky part is that users don't always type what you expect. They might press Enter without typing anything, type "ten" instead of 10, or add extra spaces. Robust programs validate input and ask again politely instead of crashing.

In this lesson you'll read text and numbers, deal with the nullable result of ReadLine, write a loop that keeps asking until the input is valid, format output so it's easy to read, and read command-line arguments passed when the program starts.

Reading a line of text

C#
Console.Write("What's your name? ");
string? name = Console.ReadLine();
Console.WriteLine($"Nice to meet you, {name}!");
  • Console.Write keeps the cursor on the same line, which suits prompts.
  • ReadLine waits for the user to press Enter and returns everything they typed, without the new line.
  • It returns string? (a string that might be null), because input can end, for example when it's redirected from a file. Console.ReadLine() ?? "" replaces null with an empty string.

Reading numbers safely

Everything typed arrives as text, so numbers must be converted:

C#
Console.Write("How many tickets? ");
string? text = Console.ReadLine();

if (int.TryParse(text, out int tickets) && tickets > 0)
{
    Console.WriteLine($"Booking {tickets} tickets");
}
else
{
    Console.WriteLine("Please enter a positive whole number.");
}

TryParse returns false for empty, null or invalid text instead of throwing an exception, so it's the right choice for anything a person types. Use double.TryParse or decimal.TryParse for decimals.

Asking until the input is valid

Wrap the prompt in a loop that only ends when the input is acceptable:

C#
int age;
while (true)
{
    Console.Write("Age: ");
    if (int.TryParse(Console.ReadLine(), out age) && age is >= 0 and <= 120)
        break;
    Console.WriteLine("Please enter an age between 0 and 120.");
}

age is >= 0 and <= 120 is a pattern that checks a range in one readable expression. Putting this logic in a helper method, such as ReadInt(string prompt, int min, int max), keeps the rest of the program tidy.

Command-line arguments and extras

Values typed after the program name arrive in args: running dotnet run -- report.csv 10 gives args[0] == "report.csv" and args[1] == "10". Check args.Length before using them.

  • Console.ReadKey() reads a single key press without Enter, useful for menus.
  • Console.ForegroundColor = ConsoleColor.Green; changes the text colour, and Console.ResetColor() restores it.
  • Console.Clear() clears the screen.

Reading until the input ends

ReadLine returns null when there's no more input. That happens when someone presses Ctrl+Z then Enter on Windows or Ctrl+D on macOS and Linux, and when input comes from a file. You can use it to process any number of lines:

C#
int total = 0;
string? line;
while ((line = Console.ReadLine()) != null)
{
    if (int.TryParse(line, out int n))
        total += n;
}
Console.WriteLine($"Total: {total}");

Run it with dotnet run < numbers.txt and the program reads the file as if someone had typed each line. Redirecting input like this is a quick way to test a console program without typing the same values over and over.

Error output and exit codes

Programs have two output streams. Console.WriteLine writes to standard output, and Console.Error.WriteLine writes to standard error. Both appear in the terminal, but when a user saves your output to a file with > results.txt, error messages still show on screen instead of mixing with the results.

A program also finishes with an exit code: 0 means success and anything else means something went wrong. Scripts and build tools check this number. With top-level statements, you can simply return it:

C#
if (args.Length == 0)
{
    Console.Error.WriteLine("Usage: report <file>");
    return 1;
}
Console.WriteLine($"Reading {args[0]}");
return 0;

In a classic program, declare static int Main(string[] args) and return the code in the same way.

C# Basics Syntax

Input and output

Console.Write("Prompt: ");
string input = Console.ReadLine() ?? "";
string clean = input.Trim();
if (int.TryParse(clean, out int n)) { /* use n */ }
if (decimal.TryParse(clean, out decimal amount)) { }
bool yes = clean.Equals("y", StringComparison.OrdinalIgnoreCase);
ConsoleKeyInfo key = Console.ReadKey();
Console.ForegroundColor = ConsoleColor.Red;
Console.ResetColor();
if (args.Length > 0) Console.WriteLine(args[0]);

C# Basics Summary

  • Console.Write prints a prompt; Console.ReadLine reads a line as string?.
  • Use ?? to replace a null result with a default.
  • Convert input with int.TryParse or decimal.TryParse, never assuming it's valid.
  • Loop until input passes validation, with a clear message each time.
  • Command-line arguments arrive in args; check args.Length first.

C# Basics Examples

Each example shows the code, the output it produces and what each part does.

Example 1

A greeting with a default

C#
Console.Write("Name (press Enter to skip): ");
string name = Console.ReadLine()?.Trim() ?? "";

if (string.IsNullOrWhiteSpace(name))
{
    name = "friend";
}

Console.WriteLine($"Hello, {name}!");
Console.WriteLine($"Your name has {name.Length} letters.");
Output
Name (press Enter to skip): Grace
Hello, Grace!
Your name has 5 letters.
Line-by-line explanation
  1. Line 2?. trims only if the result isn't null, and ?? supplies an empty string if it is.
  2. Lines 4 to 7An empty answer is replaced with a friendly default.
  3. Lines 9 to 10The output shows a run where the user typed Grace.
Example 2

A validated number

C#
int ReadInt(string prompt, int min, int max)
{
    while (true)
    {
        Console.Write(prompt);
        string? text = Console.ReadLine();
        if (int.TryParse(text, out int value) && value >= min && value <= max)
        {
            return value;
        }
        Console.WriteLine($"Please enter a whole number from {min} to {max}.");
    }
}

int qty = ReadInt("Quantity (1-10): ", 1, 10);
decimal price = 4.50m;
Console.WriteLine($"{qty} x {price:F2} = {qty * price:F2}");
Output
Quantity (1-10): lots
Please enter a whole number from 1 to 10.
Quantity (1-10): 25
Please enter a whole number from 1 to 10.
Quantity (1-10): 3
3 x 4.50 = 13.50
Line-by-line explanation
  1. Line 1A local function keeps the validation logic in one reusable place.
  2. Line 3The loop only ends when return runs.
  3. Line 7Both the conversion and the range must pass.
  4. Line 15The caller gets a valid number without worrying about bad input.
  5. Line 17:F2 formats both amounts with two decimal places.
Example 3

A yes or no menu with arguments

C#
string user = args.Length > 0 ? args[0] : "guest";
Console.WriteLine($"Signed in as {user}");

Console.Write("Show the report? (y/n): ");
string answer = (Console.ReadLine() ?? "").Trim().ToLower();

if (answer is "y" or "yes")
{
    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine("Sales: 1,204 orders this week");
    Console.ResetColor();
}
else
{
    Console.WriteLine("Report skipped.");
}
Output
Signed in as maria
Show the report? (y/n): YES
Sales: 1,204 orders this week
Line-by-line explanation
  1. Line 1The output shows a run started with dotnet run -- maria; without an argument the user is "guest".
  2. Line 5Trimming and lowercasing means "YES", " y " and "Yes" all work.
  3. Line 7The or pattern checks two values at once.
  4. Lines 9 to 11The text turns green, and ResetColor restores the normal colour.

Common C# Basics Mistakes

int.Parse on user input

Don't
int age = int.Parse(Console.ReadLine());   // crashes with FormatException on "abc"
Do
if (!int.TryParse(Console.ReadLine(), out int age))
{
    Console.WriteLine("Please type a number.");
}

Ignoring the possible null

Don't
string name = Console.ReadLine();        // warning CS8600: converting null to non-nullable type
Console.WriteLine(name.ToUpper());       // could throw NullReferenceException
Do
string name = Console.ReadLine() ?? "";
Console.WriteLine(name.ToUpper());

Reading args without checking

Don't
string file = args[0];                   // IndexOutOfRangeException when no argument is given
Do
if (args.Length == 0)
{
    Console.WriteLine("Usage: report <file>");
    return;
}
string file = args[0];

C# Basics in Real Projects

Console apps in practice

Developers write console tools to import data, run database migrations, clean up files and call APIs on a schedule. They take settings from command-line arguments, validate everything carefully, and print clear progress and errors. Libraries such as System.CommandLine and Spectre.Console add argument parsing, coloured tables and progress bars to the same basic ideas.

C# Basics FAQ

Why does Console.ReadLine return a nullable string?

ReadLine returns null when the input stream ends, for example when input is redirected from a file that has no more lines. The ? warns you about this so you handle it, either with ?? "" or a null check. When a person is typing interactively, you normally get a string, even an empty one.

How do I read an integer from the console in C#?

Read the line with Console.ReadLine() and convert it with int.TryParse, which returns false instead of throwing when the text isn't a valid number. Put the prompt in a loop so the user can try again after a mistake. int.Parse works too, but crashes with a FormatException on input such as "ten".

How do I pass command-line arguments with dotnet run?

Put them after a double dash: dotnet run -- input.txt 5. Everything after -- goes to your program in the args array, so args[0] is "input.txt" and args[1] is "5". Without the --, dotnet may try to treat them as its own options.

How do I wait for a key press before the console closes?

Add Console.ReadKey(); at the end of the program; it waits for one key and doesn't need Enter. This is mainly useful when a program is started by double-clicking, because the window closes as soon as the program ends. When you run from a terminal, the output stays visible anyway.

How do I print coloured text in the console?

Set Console.ForegroundColor to a value such as ConsoleColor.Red, write your text, then call Console.ResetColor() so later output goes back to normal. Console.BackgroundColor changes the background in the same way. Colours appear in most terminals but are lost when the output is redirected to a file.

C# Basics Exercises

Answer each one and check it instantly. If you get stuck, open the hint before the answer.

Fill in the blankseasy

Complete the line that reads what the user types.

string? text = Console.();
Multiple choiceeasy

What type does Console.ReadLine return?

Predict the outputmedium

The user types 42 . What does this print?

bool ok = int.TryParse(Console.ReadLine(), out int n);
Console.WriteLine(ok ? n + 1 : -1);
Multiple choicemedium

What does Console.ReadLine() ?? "" do?

Multiple choicehard

How do you pass "data.csv" to args[0]?

C# Basics Quiz

5 questions to check what you learned.

  1. Which method prints without moving to a new line?

    • Console.WriteLine
    • Console.Write
    • Console.Print
    • Console.Out
  2. Why use int.TryParse rather than int.Parse for user input?

    • It's shorter
    • It accepts decimals
    • It reads from the console automatically
    • It returns false for invalid text instead of throwing an exception
  3. What does Console.ReadKey do?

    • Reads a single key press
    • Reads a whole line
    • Reads a file
    • Returns the last key typed earlier
  4. What does answer is "y" or "yes" check?

    • That answer contains y
    • That answer is a bool
    • That answer equals "y" or equals "yes"
    • Nothing, it's invalid
  5. How do you restore the console's normal colour after changing it?

    • Console.Clear()
    • Console.ResetColor()
    • Console.ForegroundColor = null
    • Restart the program