HOWTO · Csharp

How to Exit Console Application in C#

Choose between returning from Main and terminating a C# console application immediately, with clear exit-code and cleanup behavior.

On this page

To exit a C# console application after its work is complete, return from Main. Use Environment.Exit() only when the process must stop immediately from another method. Returning an integer from Main, or passing one to Environment.Exit(int), supplies the process exit code; console text is separate from that code.

Return from Main to End the Application

A return statement ends the current method. When it ends Main, normal application execution finishes; statements after the return do not run. A return from a nested method only hands control back to its caller, so it does not by itself end the application. Prefer returning from Main for ordinary completion because it follows the normal control flow and allows surrounding finally blocks and resource cleanup to run.

A void Main() can use return; to finish without a value. An int Main() can return an exit code. This complete example prints a status line and returns the conventional success code. The supplied runtime observation produced Work completed. and exit code 0.

Run this example:

using System;

class Program
{
    static int Main()
    {
        Console.WriteLine("Work completed.");
        return 0;
    }
}
Work completed.

The return 0; ends Main, and the operating system or calling process receives 0. If you need to signal failure, return a nonzero code instead. The exact meaning of each nonzero value is defined by your program or its caller.

Use Environment.Exit() to Terminate from Any Method

Environment.Exit(int) can terminate the process from a method other than Main. It ends the process immediately with the supplied integer exit code and does not return to the caller. Keep it for situations where normal unwinding cannot be used, such as a deliberate immediate shutdown; ordinary error handling should generally report the problem and return an appropriate code from Main.

This complete example calls Environment.Exit(0) from StopApplication, a method other than Main:

using System;

class Program
{
    static void Main()
    {
        StopApplication();
        Console.WriteLine("This line is not reached.");
    }

    static void StopApplication()
    {
        Console.WriteLine("Stopping now.");
        Environment.Exit(0);
    }
}

The call supplies exit code 0 and terminates the process before StopApplication returns, so control never reaches the next line in Main. The supplied runtime observation covers the Main example above, not this example. A call such as Environment.Exit(1); instead supplies exit code 1; the integer is passed to the operating system or calling process, while any message printed with Console.WriteLine is separate console output. The method is static on System.Environment, so a file using using System; can call it directly.

Choose an Exit Code and Understand Cleanup

Use 0 by convention to indicate success and a nonzero value to indicate failure. These are conventions rather than a universal mapping for every application: document any codes that a script, service manager, or other caller must interpret. Returning an integer from Main and calling Environment.Exit(int) both communicate a process exit code. Neither value is printed automatically, so print a separate diagnostic when a person needs to see an explanation.

Prefer returning from Main when the program can finish normally. Normal method return allows finally blocks to run as control leaves their try statements, and scoped resources such as using declarations can be disposed as their scopes end. Environment.Exit() stops the process immediately, so normal stack unwinding does not occur; pending finally blocks and managed cleanup are skipped. Flush or close important resources through normal control flow before using immediate termination, and avoid it when cleanup is needed to preserve data or release resources.

Distinguish Process Exit from Loop Breaks, Exceptions, and Ctrl+C

A break statement exits its nearest loop or switch; execution continues after that construct. If leaving a loop should finish the program, let execution reach the end of Main or return from Main after the loop.

Throwing an exception transfers control to a matching handler. If the handler catches it and execution continues, the process has not exited. Handle the condition, then choose a normal return path and suitable exit code if the application should finish. An unhandled exception can end a process, but using one solely as a termination shortcut obscures the intended control flow and error handling.

Ctrl+C is a cancellation request from the console, not a guaranteed graceful-exit command. A program can observe it through Console.CancelKeyPress; whether the process stops immediately or the handler cancels the default response depends on the event handling and host environment. If cancellation needs cleanup, record the request and let the main control flow stop its work and return normally.