This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can trysigning in orchanging directories.
Access to this page requires authorization. You can trychanging directories.
TheMain
method is the entry point of a C# application. When the application is started, theMain
method is the first method that is invoked.
There can only be one entry point in a C# program. If you have more than one class that has aMain
method, you must compile your program with theStartupObject compiler option to specify whichMain
method to use as the entry point. For more information, seeStartupObject (C# Compiler Options). The following example displays the number of command line arguments as its first action:
class TestClass{ static void Main(string[] args) { Console.WriteLine(args.Length); }}
You can also use top-level statements in one file as the entry point for your application. Just as theMain
method, top-level statements can alsoreturn values and accesscommand-line arguments. For more information, seeTop-level statements. The following example uses aforeach
loop to display the command-line arguments using theargs
variable, and at the end of the program returns a success code (0
):
using System.Text;StringBuilder builder = new();builder.AppendLine("The following arguments are passed:");foreach (var arg in args){ builder.AppendLine($"Argument={arg}");}Console.WriteLine(builder.ToString());return 0;
Beginning with C# 14, programs can befile based programs, where a single file contains the program. You runfile based programs with the commanddotnet run <file.cs>
, or using the#!/usr/local/share/dotnet/dotnet run
directive as the first line (unix shells only).
Main
method is the entry point of an executable program; it's where the program control starts and ends.Main
must be declared inside a class or struct. The enclosingclass
can bestatic
.Main
must bestatic
.Main
can have anyaccess modifier (exceptfile
).Main
can either have avoid
,int
,Task
, orTask<int>
return type.Main
returns aTask
orTask<int>
, the declaration ofMain
can include theasync
modifier. This rule specifically excludes anasync void Main
method.Main
method can be declared with or without astring[]
parameter that contains command-line arguments. When using Visual Studio to create Windows applications, you can add the parameter manually or else use theGetCommandLineArgs() method to obtain the command-line arguments. Parameters are read as zero-indexed command-line arguments. Unlike C and C++, the name of the program isn't treated as the first command-line argument in theargs
array, but it's the first element of theGetCommandLineArgs() method.The following list shows the most commonMain
declarations:
static void Main() { }static int Main() { }static void Main(string[] args) { }static int Main(string[] args) { }static async Task Main() { }static async Task<int> Main() { }static async Task Main(string[] args) { }static async Task<int> Main(string[] args) { }
The preceding examples don't specify an access modifier, so they're implicitlyprivate
by default. It's possible to specify any explicit access modifier.
Tip
The addition ofasync
andTask
,Task<int>
return types simplifies program code when console applications need to start andawait
asynchronous operations inMain
.
You can return anint
from theMain
method by defining the method in one of the following ways:
Main declaration | Main method code |
---|---|
static int Main() | No use ofargs orawait |
static int Main(string[] args) | Usesargs but notawait |
static async Task<int> Main() | Usesawait but notargs |
static async Task<int> Main(string[] args) | Usesargs andawait |
If the return value fromMain
isn't used, returningvoid
orTask
allows for slightly simpler code.
Main declaration | Main method code |
---|---|
static void Main() | No use ofargs orawait |
static void Main(string[] args) | Usesargs but notawait |
static async Task Main() | Usesawait but notargs |
static async Task Main(string[] args) | Usesargs andawait |
However, returningint
orTask<int>
enables the program to communicate status information to other programs or scripts that invoke the executable file.
The following example shows how the exit code for the process can be accessed.
This example uses.NET Core command-line tools. If you're unfamiliar with .NET Core command-line tools, you can learn about them in thisget-started article.
Create a new application by runningdotnet new console
. Modify theMain
method inProgram.cs as follows:
class MainReturnValTest{ static int Main() { //... return 0; }}
Remember to save this program asMainReturnValTest.cs.
When a program is executed in Windows, any value returned from theMain
function is stored in an environment variable. This environment variable can be retrieved usingERRORLEVEL
from a batch file, or$LastExitCode
from PowerShell.
You can build the application using thedotnet CLIdotnet 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 astest.ps1
in the folder that contains the project. Run the PowerShell script by typingtest.ps1
at the PowerShell prompt.
Because the code returns zero, the batch file reports success. However, if you change MainReturnValTest.cs to return a non-zero value and then recompile the program, subsequent execution of the PowerShell script reports failure.
dotnet runif ($LastExitCode -eq 0) { Write-Host "Execution succeeded"} else{ Write-Host "Execution Failed"}Write-Host "Return value = " $LastExitCode
Execution succeededReturn value = 0
When you declare anasync
return value forMain
, the compiler generates the boilerplate code for calling asynchronous methods inMain
:
class Program{ static async Task<int> Main(string[] args) { return await AsyncConsoleWork(); } private static async Task<int> AsyncConsoleWork() { return 0; }}
In both examples main body of the program is within the body ofAsyncConsoleWork()
method.
An advantage of declaringMain
asasync
is that the compiler always generates the correct code.
When the application entry point returns aTask
orTask<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 usedasync
modifier on theMain
method, the compiler would generate the same code.
You can send arguments to theMain
method by defining the method in one of the following ways:
Main declaration | Main method code |
---|---|
static void Main(string[] args) | No return value orawait |
static int Main(string[] args) | Returns a value but doesn't useawait |
static async Task Main(string[] args) | Usesawait but doesn't return a value |
static async Task<int> Main(string[] args) | Return a value and usesawait |
If the arguments aren't used, you can omitargs
from the method declaration for slightly simpler code:
Main declaration | Main method code |
---|---|
static void Main() | No return value orawait |
static int Main() | Returns a value but doesn't useawait |
static async Task Main() | Usesawait but doesn't return a value |
static async Task<int> Main() | Returns a value and usesawait |
Note
You can also useEnvironment.CommandLine orEnvironment.GetCommandLineArgs to access the command-line arguments from any point in a console or Windows Forms application. To enable command-line arguments in theMain
method declaration in a Windows Forms application, you must manually modify the declaration ofMain
. The code generated by the Windows Forms designer createsMain
without an input parameter.
The parameter of theMain
method is aString array that represents the command-line arguments. Usually you determine whether arguments exist by testing theLength
property, for example:
if (args.Length == 0){ System.Console.WriteLine("Please enter a numeric argument."); return 1;}
Tip
Theargs
array can't be null. So, it's safe to access theLength
property without null checking.
You can also convert the string arguments to numeric types by using theConvert class or theParse
method. For example, the following statement converts thestring
to along
number by using theParse method:
long num = Int64.Parse(args[0]);
It's also possible to use the C# typelong
, which aliasesInt64
:
long num = long.Parse(args[0]);
You can also use theConvert
class methodToInt64
to do the same thing:
long num = Convert.ToInt64(s);
For more information, seeParse andConvert.
Tip
Parsing command-line arguments can be complex. Consider using theSystem.CommandLine library (currently in beta) to simplify the process.
The following example shows how to use command-line arguments in a console application. The application takes one argument at run time, converts the argument to an integer, and calculates the factorial of the number. If no arguments are supplied, the application issues a message that explains the correct usage of the program.
To compile and run the application from a command prompt, follow these steps:
Paste the following code into any text editor, and then save the file as a text file with the nameFactorial.cs.
public class Functions{ public static long Factorial(int n) { // Test for invalid input. if ((n < 0) || (n > 20)) { return -1; } // Calculate the factorial iteratively rather than recursively. long tempResult = 1; for (int i = 1; i <= n; i++) { tempResult *= i; } return tempResult; }}class MainClass{ static int Main(string[] args) { if (args.Length == 0) { Console.WriteLine("Please enter a numeric argument."); Console.WriteLine("Usage: Factorial <num>"); return 1; } int num; bool test = int.TryParse(args[0], out num); if (!test) { Console.WriteLine("Please enter a numeric argument."); Console.WriteLine("Usage: Factorial <num>"); return 1; } long result = Functions.Factorial(num); if (result == -1) Console.WriteLine("Input must be >= 0 and <= 20."); else Console.WriteLine($"The Factorial of {num} is {result}."); return 0; }}
At the beginning of theMain
method the program tests if input arguments weren't supplied comparing length ofargs
argument to0
and displays the help if no arguments are found.
If arguments are provided (args.Length
is greater than 0), the program tries to convert the input arguments to numbers. This example throws an exception if the argument isn't a number.
After factorial is calculated (stored inresult
variable of typelong
), the verbose result is printed depending on theresult
variable.
From theStart screen orStart menu, open a Visual StudioDeveloper Command Prompt window, and then navigate to the folder that contains the file that you created.
To compile the application, enter the following command:
dotnet build
If your application has no compilation errors, a binary file namedFactorial.dll is created.
Enter the following command to calculate the factorial of 3:
dotnet run -- 3
If 3 is entered on command line as the program's argument, the output reads:The factorial of 3 is 6.
Note
When running an application in Visual Studio, you can specify command-line arguments in theDebug Page, Project Designer.
For more information, see theC# Language Specification. The language specification is the definitive source for C# syntax and usage.
Was this page helpful?
Was this page helpful?