Main() return values (C# Programming Guide)
The Main
method can return void
:
static void Main()
{
//...
}
It can also return an int
:
static int Main()
{
//...
return 0;
}
If the return value from Main
is not used, returning void
allows for slightly simpler code. However, returning an integer enables the program to communicate status information to other programs or scripts that invoke the executable file. The return value from Main
is treated as the exit code for the process. If void
is returned from Main
the exit code will be implicitly 0
. The following example shows how the return value from Main
can be accessed.
Example
This example uses .NET Core command line tools. If you are unfamiliar with .NET Core command line tools, you can learn about them in this Get started topic.
Modify the Main
method in program.cs as follows:
// Save this program as MainReturnValTest.cs.
class MainReturnValTest
{
static int Main()
{
//...
return 0;
}
}
When a program is executed in Windows, any value returned from the Main
function is stored in an environment variable. This environment variable can be retrieved using ERRORLEVEL
from a batch file, or $LastExitCode
from powershell.
You can build the application using the dotnet CLI dotnet build
command.
Next, create a Powershell script to run the application and display the result. Paste the following code into a text file and save it as test.ps1
in the folder that contains the project. Run the powershell script by typing test.ps1
at the powershell prompt.
Because the code returns zero, the batch file will report success. However, if you change MainReturnValTest.cs to return a non-zero value and then re-compile the program, subsequent execution of the powershell script will report failure.
dotnet run
if ($LastExitCode -eq 0) {
Write-Host "Execution succeeded"
} else
{
Write-Host "Execution Failed"
}
Write-Host "Return value = " $LastExitCode
Sample output
Execution succeeded
Return value = 0
Async Main return values
Async Main return values move the boilerplate code necessary for calling asynchronous methods in Main
to code generated by the compiler. Previously, you would need to write this construct to call asynchronous code and ensure your program ran until the asynchronous operation completed:
public static void Main()
{
AsyncConsoleWork().GetAwaiter().GetResult();
}
private static async Task<int> AsyncConsoleWork()
{
// Main body here
return 0;
}
Now, this can be replaced by:
static async Task<int> Main(string[] args)
{
return await AsyncConsoleWork();
}
The advantage of the new syntax is that the compiler always generates the correct code.
Compiler generated code
When the application entry point returns a Task
or Task<int>
, the compiler generates a new entry point that calls the entry point method declared in the application code. Assuming that this entry point is called $GeneratedMain
, the compiler generates the following code for these entry points:
static Task Main()
results in the compiler emitting the equivalent ofprivate static void $GeneratedMain() => Main().GetAwaiter().GetResult();
static Task Main(string[])
results in the compiler emitting the equivalent ofprivate static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
static Task<int> Main()
results in the compiler emitting the equivalent ofprivate static int $GeneratedMain() => Main().GetAwaiter().GetResult();
static Task<int> Main(string[])
results in the compiler emitting the equivalent ofprivate static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
Note
If the examples used async
modifier on the Main
method, the compiler would generate the same code.
See also
Feedback
Loading feedback...