ℹ️ Skipped - page is already crawled
| Filter | Status | Condition | Details |
|---|---|---|---|
| HTTP status | PASS | download_http_code = 200 | HTTP 200 |
| Age cutoff | PASS | download_stamp > now() - 6 MONTH | 1.2 months ago (distributed domain, exempt) |
| History drop | PASS | isNull(history_drop_reason) | No drop reason |
| Spam/ban | PASS | fh_dont_index != 1 AND ml_spam_score = 0 | ml_spam_score=0 |
| Canonical | PASS | meta_canonical IS NULL OR = '' OR = src_unparsed | Not set |
| Property | Value |
|---|---|
| URL | https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line |
| Last Crawled | 2026-03-06 00:15:32 (1 month ago) |
| First Indexed | 2022-09-18 12:51:17 (3 years ago) |
| HTTP Status Code | 200 |
| Meta Title | Main() and command-line arguments - C# | Microsoft Learn |
| Meta Description | Learn about Main() and command-line arguments. The 'Main' method is the entry point of an executable program. |
| Meta Canonical | null |
| Boilerpipe Text | The runtime calls the
Main
method when you start a C# application. The
Main
method is the entry point of a C# application.
A C# program can have only one entry point. If you have more than one class with a
Main
method, you must use the
StartupObject
compiler option when you compile your program to specify which
Main
method serves as the entry point. For more information, see
StartupObject
(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. Like the
Main
method, top-level statements can
return values
and access
command-line arguments
. For more information, see
Top-level statements
. The following example uses a
foreach
loop to display the command-line arguments by using the
args
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 be
file-based apps
, where a single file contains the program. You run
file-based apps
by using the command
dotnet <file.cs>
, or by using the
#!/usr/bin/env dotnet run
directive as the first line (Unix shells only).
The
Main
method is the entry point of an executable program. It's where the program control starts and ends.
You must declare
Main
inside a class or struct. The enclosing
class
can be
static
.
Main
must be
static
.
Main
can have any
access modifier
.
Main
can return
void
,
int
,
Task
, or
Task<int>
.
If and only if
Main
returns a
Task
or
Task<int>
, the declaration of
Main
can include the
async
modifier. This rule specifically excludes an
async void Main
method.
You can declare the
Main
method with or without a
string[]
parameter that contains command-line arguments. When using Visual Studio to create Windows applications, you can add the parameter manually or else use the
GetCommandLineArgs()
method to obtain the command-line arguments. Parameters are zero-indexed command-line arguments. Unlike C and C++, the name of the program isn't treated as the first command-line argument in the
args
array, but it's the first element of the
GetCommandLineArgs()
method.
The following list shows the most common
Main
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 implicitly
private
by default. You can specify any explicit access modifier.
Tip
By using
async
and
Task
or
Task<int>
return types, you simplify program code when console applications need to start and
await
asynchronous operations in
Main
.
You can return an
int
from the
Main
method by defining the method in one of the following ways:
Main
declaration
Main
method code
static int Main()
No use of
args
or
await
static int Main(string[] args)
Uses
args
but not
await
static async Task<int> Main()
Uses
await
but not
args
static async Task<int> Main(string[] args)
Uses
args
and
await
If the return value from
Main
isn't used, returning
void
or
Task
allows for slightly simpler code.
Main
declaration
Main
method code
static void Main()
No use of
args
or
await
static void Main(string[] args)
Uses
args
but not
await
static async Task Main()
Uses
await
but not
args
static async Task Main(string[] args)
Uses
args
and
await
However, returning
int
or
Task<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 this
get-started article
.
Create a new application by running
dotnet new console
. Modify the
Main
method in
Program.cs
as follows:
class
MainReturnValTest
{
static
int
Main
(
)
{
//...
return
0
;
}
}
Remember to save this program as
MainReturnValTest.cs
.
When you execute a program in Windows, the system stores any value returned from the
Main
function in an environment variable. You can retrieve this environment variable by using
ERRORLEVEL
from a batch file, or
$LastExitCode
from PowerShell.
You can build the application by 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 reports success. However, if you change MainReturnValTest.cs to return a nonzero value and then recompile the program, subsequent execution of the PowerShell script reports failure.
dotnet run
if
(
$LastExitCode
-eq
0
) {
Write-Host
"Execution succeeded"
}
else
{
Write-Host
"Execution Failed"
}
Write-Host
"Return value = "
$LastExitCode
Execution succeeded
Return value = 0
When you declare an
async
return value for
Main
, the compiler generates the boilerplate code for calling asynchronous methods in
Main
:
class
Program
{
static
async
Task<
int
>
Main
(
string
[] args
)
{
return
await
AsyncConsoleWork();
}
private
static
async
Task<
int
>
AsyncConsoleWork
(
)
{
return
0
;
}
}
In both examples, the main body of the program is within the body of the
AsyncConsoleWork()
method.
An advantage of declaring
Main
as
async
is that the compiler always generates the correct 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 of
private static void $GeneratedMain() => Main().GetAwaiter().GetResult();
.
static Task Main(string[])
results in the compiler emitting the equivalent of
private static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
.
static Task<int> Main()
results in the compiler emitting the equivalent of
private static int $GeneratedMain() => Main().GetAwaiter().GetResult();
.
static Task<int> Main(string[])
results in the compiler emitting the equivalent of
private static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();
.
Note
If the examples use the
async
modifier on the
Main
method, the compiler generates the same code.
You can send arguments to the
Main
method by defining the method in one of the following ways:
Main
declaration
Main
method code
static void Main(string[] args)
No return value or
await
static int Main(string[] args)
Returns a value but doesn't use
await
static async Task Main(string[] args)
Uses
await
but doesn't return a value
static async Task<int> Main(string[] args)
Return a value and uses
await
If you don't use the arguments, you can omit
args
from the method declaration for slightly simpler code:
Main
declaration
Main
method code
static void Main()
No return value or
await
static int Main()
Returns a value but doesn't use
await
static async Task Main()
Uses
await
but doesn't return a value
static async Task<int> Main()
Returns a value and uses
await
Note
You can also use
Environment.CommandLine
or
Environment.GetCommandLineArgs
to access the command-line arguments from any point in a console or Windows Forms application. To enable command-line arguments in the
Main
method declaration in a Windows Forms application, you must manually modify the declaration of
Main
. The code generated by the Windows Forms designer creates
Main
without an input parameter.
The parameter of the
Main
method is a
String
array that represents the command-line arguments. Usually, you determine whether arguments exist by testing the
Length
property, for example:
if
(args.Length ==
0
)
{
System.Console.WriteLine(
"Please enter a numeric argument."
);
return
1
;
}
Tip
The
args
array can't be null. So, it's safe to access the
Length
property without null checking.
You can also convert the string arguments to numeric types by using the
Convert
class or the
Parse
method. For example, the following statement converts the
string
to a
long
number by using the
Parse
method:
long
num = Int64.Parse(args[
0
]);
It's also possible to use the C# type
long
, which aliases
Int64
:
long
num =
long
.Parse(args[
0
]);
You can also use the
Convert
class method
ToInt64
to do the same thing:
long
num = Convert.ToInt64(s);
For more information, see
Parse
and
Convert
.
Tip
Parsing command-line arguments can be complex. Consider using the
System.CommandLine
library 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 name
Factorial.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 the
Main
method, the program tests if input arguments weren't supplied by comparing the length of the
args
argument to
0
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 in
result
variable of type
long
), the verbose result is printed depending on the
result
variable.
From the
Start
screen or
Start
menu, open a Visual Studio
Developer 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, the build process creates a binary file named
Factorial.dll
.
Enter the following command to calculate the factorial of 3:
dotnet run -- 3
If you enter 3 on the command line as the program's argument, the output reads:
The factorial of 3 is 6.
For more information, see the
C# Language Specification
. The language specification is the definitive source for C# syntax and usage.
System.Environment
How to display command line arguments |
| Markdown | [Skip to main content](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#main) [Skip to Ask Learn chat experience](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line)
Go deep on real code and real systems at Microsoft Build 2026, June 2-3 in San Francisco and online [Get started](https://aka.ms/MSBuild_FY26_BN_MSLearn_Txt)
Dismiss alert
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
[Download Microsoft Edge](https://go.microsoft.com/fwlink/p/?LinkID=2092881%20) [More info about Internet Explorer and Microsoft Edge](https://learn.microsoft.com/en-us/lifecycle/faq/internet-explorer-microsoft-edge)
[Learn](https://learn.microsoft.com/en-us/)
[Sign in](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line)
![]()
![]()
- [Profile](https://learn.microsoft.com/en-us/users/me/activity/)
- [Settings](https://learn.microsoft.com/en-us/users/me/settings/)
[Sign out](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line)
[Learn](https://learn.microsoft.com/en-us/)
- Documentation
- [All product documentation](https://learn.microsoft.com/en-us/docs/)
- [Azure documentation](https://learn.microsoft.com/en-us/azure/?product=popular)
- [Dynamics 365 documentation](https://learn.microsoft.com/en-us/dynamics365/)
- [Microsoft Copilot documentation](https://learn.microsoft.com/en-us/copilot/)
- [Microsoft 365 documentation](https://learn.microsoft.com/en-us/microsoft-365/)
- [Power Platform documentation](https://learn.microsoft.com/en-us/power-platform/)
- [Code samples](https://learn.microsoft.com/en-us/samples/)
- [Troubleshooting documentation](https://learn.microsoft.com/en-us/troubleshoot/)
Free to join. Request to attend.
[Microsoft AI Tour](https://aitour.microsoft.com/?wt.mc_id=itour26_learnmarketingspot_wwl)
Take your business to the AI frontier.
- Training & Labs
- [All training](https://learn.microsoft.com/en-us/training/)
- [Azure training](https://learn.microsoft.com/en-us/training/browse/?products=azure)
- [Dynamics 365 training](https://learn.microsoft.com/en-us/training/browse/?products=dynamics-365)
- [Microsoft Copilot training](https://learn.microsoft.com/en-us/training/browse/?products=ms-copilot)
- [Microsoft 365 training](https://learn.microsoft.com/en-us/training/browse/?products=m365)
- [Microsoft Power Platform training](https://learn.microsoft.com/en-us/training/browse/?products=power-platform)
- [Labs](https://learn.microsoft.com/en-us/labs/)
- [Credentials](https://learn.microsoft.com/en-us/credentials/)
- [Career paths](https://learn.microsoft.com/en-us/training/career-paths/)
Free to join. Request to attend.
[Microsoft AI Tour](https://aitour.microsoft.com/?wt.mc_id=itour26_learnmarketingspot_wwl)
Take your business to the AI frontier.
- Q\&A
- [Ask a question](https://learn.microsoft.com/en-us/answers/questions/ask/)
- [Azure questions](https://learn.microsoft.com/en-us/answers/tags/133/azure/)
- [Windows questions](https://learn.microsoft.com/en-us/answers/tags/60/windows/)
- [Microsoft 365 questions](https://learn.microsoft.com/en-us/answers/tags/9/m365/)
- [Microsoft Outlook questions](https://learn.microsoft.com/en-us/answers/tags/131/office-outlook/)
- [Microsoft Teams questions](https://learn.microsoft.com/en-us/answers/tags/108/office-teams/)
- [Popular tags](https://learn.microsoft.com/en-us/answers/tags/)
- [All questions](https://learn.microsoft.com/en-us/answers/questions/)
Free to join. Request to attend.
[Microsoft AI Tour](https://aitour.microsoft.com/?wt.mc_id=itour26_learnmarketingspot_wwl)
Take your business to the AI frontier.
- Topics
- [Artificial intelligence](https://learn.microsoft.com/en-us/ai/)
Learning hub to build AI skills
- [Compliance](https://learn.microsoft.com/en-us/compliance/)
Compliance resources you need to get started with your business
- [DevOps](https://learn.microsoft.com/en-us/devops/)
DevOps practices, Git version control and Agile methods
- [Learn for Organizations](https://learn.microsoft.com/en-us/training/organizations/)
Curated offerings from Microsoft to boost your team’s technical skills
- [Platform engineering](https://learn.microsoft.com/en-us/platform-engineering/)
Tools from Microsoft and others to build personalized developer experiences
- [Security](https://learn.microsoft.com/en-us/security/)
Guidance to help you tackle security challenges
- [Assessments](https://learn.microsoft.com/en-us/assessments/)
Interactive guidance with custom recommendations
- [Student hub](https://learn.microsoft.com/en-us/training/student-hub/)
Self-paced and interactive training for students
- [Educator center](https://learn.microsoft.com/en-us/training/educator-center/)
Resources for educators to bring technical innovation in their classroom
Free to join. Request to attend.
[Microsoft AI Tour](https://aitour.microsoft.com/?wt.mc_id=itour26_learnmarketingspot_wwl)
Take your business to the AI frontier.
[Sign in](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line)
![]()
![]()
- [Profile](https://learn.microsoft.com/en-us/users/me/activity/)
- [Settings](https://learn.microsoft.com/en-us/users/me/settings/)
[Sign out](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line)
[C\#](https://learn.microsoft.com/en-us/dotnet/csharp/)
- Fundamentals
- [Tour of C\#](https://learn.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/)
- [Fundamentals](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/)
- [What's new](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/)
- Features
- [Programming concepts](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/)
- [LINQ](https://learn.microsoft.com/en-us/dotnet/csharp/linq/)
- [Asynchronous programming](https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/)
- [Advanced topics](https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/reflection-and-attributes/)
- [.NET compiler platform SDK](https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/)
- Reference
- [Language reference](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/)
- [Types](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/built-in-types)
- [Keywords](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/)
- [Operators and expressions](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/)
- [Statements](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/declarations)
- [Special characters](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/)
- [XML documentation comments](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/xmldoc/)
- Specifications
- [Specifications](https://learn.microsoft.com/en-us/dotnet/csharp/specification/overview)
- [ECMA C\# draft](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/readme)
- [Feature Specifications](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/enhanced-line-directives)
- .NET workloads
- [Web](https://learn.microsoft.com/en-us/aspnet/core/)
- [Cloud](https://learn.microsoft.com/en-us/dotnet/azure/)
- Cloud-native
- [Aspire](https://learn.microsoft.com/en-us/dotnet/aspire/)
- [Microsoft Orleans](https://learn.microsoft.com/en-us/dotnet/orleans/)
- Desktop and mobile
- [.NET Multi-platform App UI (.NET MAUI)](https://learn.microsoft.com/en-us/dotnet/maui/)
- [Windows Presentation Foundation](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/)
- [Windows Forms](https://learn.microsoft.com/en-us/dotnet/desktop/winforms/)
- [WinUI apps](https://learn.microsoft.com/en-us/windows/apps/winui/)
- APIs
- [.NET](https://learn.microsoft.com/en-us/dotnet/api/?view=net-10.0)
- [Aspire](https://learn.microsoft.com/en-us/dotnet/api/?view=dotnet-aspire-9.0)
- [.NET Framework](https://learn.microsoft.com/en-us/dotnet/api/?view=netframework-4.8.1&preserve-view=true)
- [.NET Multi-platform App UI (.NET MAUI)](https://learn.microsoft.com/en-us/dotnet/api/?view=net-maui-9.0)
- [ASP.NET](https://learn.microsoft.com/en-us/dotnet/api/?view=aspnetcore-10.0)
- [ML.NET](https://learn.microsoft.com/en-us/dotnet/api/?view=ml-dotnet&preserve-view=true)
- More
- Fundamentals
- [Tour of C\#](https://learn.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/)
- [Fundamentals](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/)
- [What's new](https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/)
- Features
- [Programming concepts](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/)
- [LINQ](https://learn.microsoft.com/en-us/dotnet/csharp/linq/)
- [Asynchronous programming](https://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/)
- [Advanced topics](https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/reflection-and-attributes/)
- [.NET compiler platform SDK](https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/)
- Reference
- [Language reference](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/)
- [Types](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/built-in-types)
- [Keywords](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/)
- [Operators and expressions](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/)
- [Statements](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/declarations)
- [Special characters](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/)
- [XML documentation comments](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/xmldoc/)
- Specifications
- [Specifications](https://learn.microsoft.com/en-us/dotnet/csharp/specification/overview)
- [ECMA C\# draft](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/readme)
- [Feature Specifications](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/enhanced-line-directives)
- .NET workloads
- [Web](https://learn.microsoft.com/en-us/aspnet/core/)
- [Cloud](https://learn.microsoft.com/en-us/dotnet/azure/)
- Cloud-native
- [Aspire](https://learn.microsoft.com/en-us/dotnet/aspire/)
- [Microsoft Orleans](https://learn.microsoft.com/en-us/dotnet/orleans/)
- Desktop and mobile
- [.NET Multi-platform App UI (.NET MAUI)](https://learn.microsoft.com/en-us/dotnet/maui/)
- [Windows Presentation Foundation](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/)
- [Windows Forms](https://learn.microsoft.com/en-us/dotnet/desktop/winforms/)
- [WinUI apps](https://learn.microsoft.com/en-us/windows/apps/winui/)
- APIs
- [.NET](https://learn.microsoft.com/en-us/dotnet/api/?view=net-10.0)
- [Aspire](https://learn.microsoft.com/en-us/dotnet/api/?view=dotnet-aspire-9.0)
- [.NET Framework](https://learn.microsoft.com/en-us/dotnet/api/?view=netframework-4.8.1&preserve-view=true)
- [.NET Multi-platform App UI (.NET MAUI)](https://learn.microsoft.com/en-us/dotnet/api/?view=net-maui-9.0)
- [ASP.NET](https://learn.microsoft.com/en-us/dotnet/api/?view=aspnetcore-10.0)
- [ML.NET](https://learn.microsoft.com/en-us/dotnet/api/?view=ml-dotnet&preserve-view=true)
[Download .NET](https://dotnet.microsoft.com/download)
- [C\# documentation](https://learn.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/)
- Get started
- Fundamentals
- Program structure
- [Overview](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/)
- [Main method](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line)
- [Top-level statements](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements)
- Type system
- Object-oriented programming
- Functional techniques
- Exceptions and errors
- Coding style
- Tutorials
- What's new in C\#
- Tutorials
- Language-Integrated Query (LINQ)
- Asynchronous programming
- C\# concepts
- How-to C\# articles
- Advanced topics
- The .NET Compiler Platform SDK (Roslyn APIs)
- C\# programming guide
- Other C\# documentation
Download PDF
Table of contents
Exit editor mode
1. [Learn](https://learn.microsoft.com/en-us/)
2. [.NET](https://learn.microsoft.com/en-us/dotnet/)
3. [C\#](https://learn.microsoft.com/en-us/dotnet/csharp/)
1. [Learn](https://learn.microsoft.com/en-us/)
2. [.NET](https://learn.microsoft.com/en-us/dotnet/)
3. [C\#](https://learn.microsoft.com/en-us/dotnet/csharp/)
Ask Learn
Ask Learn
Focus mode
Table of contents
[Read in English](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line)
Add to Collections
Add to plan
[Edit](https://github.com/dotnet/docs/blob/main/docs/csharp/fundamentals/program-structure/main-command-line.md)
***
#### Share via
[Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fdotnet%2Fcsharp%2Ffundamentals%2Fprogram-structure%2Fmain-command-line%3FWT.mc_id%3Dfacebook) [x.com](https://twitter.com/intent/tweet?original_referer=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fdotnet%2Fcsharp%2Ffundamentals%2Fprogram-structure%2Fmain-command-line%3FWT.mc_id%3Dtwitter&tw_p=tweetbutton&url=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fdotnet%2Fcsharp%2Ffundamentals%2Fprogram-structure%2Fmain-command-line%3FWT.mc_id%3Dtwitter) [LinkedIn](https://www.linkedin.com/feed/?shareActive=true&text=%0A%0D%0Ahttps%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fdotnet%2Fcsharp%2Ffundamentals%2Fprogram-structure%2Fmain-command-line%3FWT.mc_id%3Dlinkedin) [Email](mailto:?subject=%5BShared%20Article%5D%20Main\(\)%20and%20command-line%20arguments%20-%20C%23%20%7C%20Microsoft%20Learn&body=%0A%0D%0Ahttps%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fdotnet%2Fcsharp%2Ffundamentals%2Fprogram-structure%2Fmain-command-line%3FWT.mc_id%3Demail)
***
Copy Markdown
Print
***
Note
Access to this page requires authorization. You can try [signing in](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line) or [changing directories]().
Access to this page requires authorization. You can try [changing directories]().
# Main() and command-line arguments
Feedback
Summarize this article for me
## In this article
1. [Overview](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#overview)
2. [Main() return values](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#main-return-values)
3. [Command-line arguments](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#command-line-arguments)
4. [C\# language specification](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#c-language-specification)
5. [See also](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#see-also)
The runtime calls the `Main` method when you start a C\# application. The `Main` method is the entry point of a C\# application.
A C\# program can have only one entry point. If you have more than one class with a `Main` method, you must use the **StartupObject** compiler option when you compile your program to specify which `Main` method serves as the entry point. For more information, see [**StartupObject** (C\# Compiler Options)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/advanced#startupobject). The following example displays the number of command line arguments as its first action:
C\#
Copy
```
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. Like the `Main` method, top-level statements can [return values](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#main-return-values) and access [command-line arguments](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#command-line-arguments). For more information, see [Top-level statements](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements). The following example uses a `foreach` loop to display the command-line arguments by using the `args` variable, and at the end of the program returns a success code (`0`):
C\#
Copy
```
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 be [*file-based apps*](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/#building-and-running-c-programs), where a single file contains the program. You run *file-based apps* by using the command `dotnet <file.cs>`, or by using the `#!/usr/bin/env dotnet run` directive as the first line (Unix shells only).
## Overview
- The `Main` method is the entry point of an executable program. It's where the program control starts and ends.
- You must declare `Main` inside a class or struct. The enclosing `class` can be `static`.
- `Main` must be [`static`](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/static).
- `Main` can have any [access modifier](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers).
- `Main` can return `void`, `int`, `Task`, or `Task<int>`.
- If and only if `Main` returns a `Task` or `Task<int>`, the declaration of `Main` can include the [`async`](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/async) modifier. This rule specifically excludes an `async void Main` method.
- You can declare the `Main` method with or without a `string[]` parameter that contains command-line arguments. When using Visual Studio to create Windows applications, you can add the parameter manually or else use the [GetCommandLineArgs()](https://learn.microsoft.com/en-us/dotnet/api/system.environment.getcommandlineargs#system-environment-getcommandlineargs) method to obtain the command-line arguments. Parameters are zero-indexed command-line arguments. Unlike C and C++, the name of the program isn't treated as the first command-line argument in the `args` array, but it's the first element of the [GetCommandLineArgs()](https://learn.microsoft.com/en-us/dotnet/api/system.environment.getcommandlineargs#system-environment-getcommandlineargs) method.
The following list shows the most common `Main` declarations:
C\#
Copy
```
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 implicitly `private` by default. You can specify any explicit access modifier.
Tip
By using `async` and `Task` or `Task<int>` return types, you simplify program code when console applications need to start and `await` asynchronous operations in `Main`.
## Main() return values
You can return an `int` from the `Main` method by defining the method in one of the following ways:
Expand table
| `Main` declaration | `Main` method code |
|---|---|
| `static int Main()` | No use of `args` or `await` |
| `static int Main(string[] args)` | Uses `args` but not `await` |
| `static async Task<int> Main()` | Uses `await` but not `args` |
| `static async Task<int> Main(string[] args)` | Uses `args` and `await` |
If the return value from `Main` isn't used, returning `void` or `Task` allows for slightly simpler code.
Expand table
| `Main` declaration | `Main` method code |
|---|---|
| `static void Main()` | No use of `args` or `await` |
| `static void Main(string[] args)` | Uses `args` but not `await` |
| `static async Task Main()` | Uses `await` but not `args` |
| `static async Task Main(string[] args)` | Uses `args` and `await` |
However, returning `int` or `Task<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](https://learn.microsoft.com/en-us/dotnet/core/introduction) command-line tools. If you're unfamiliar with .NET Core command-line tools, you can learn about them in this [get-started article](https://learn.microsoft.com/en-us/dotnet/core/tutorials/create-console-app).
Create a new application by running `dotnet new console`. Modify the `Main` method in *Program.cs* as follows:
C\#
Copy
```
class MainReturnValTest
{
static int Main()
{
//...
return 0;
}
}
```
Remember to save this program as *MainReturnValTest.cs*.
When you execute a program in Windows, the system stores any value returned from the `Main` function in an environment variable. You can retrieve this environment variable by using `ERRORLEVEL` from a batch file, or `$LastExitCode` from PowerShell.
You can build the application by using the [dotnet CLI](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet) `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 reports success. However, if you change MainReturnValTest.cs to return a nonzero value and then recompile the program, subsequent execution of the PowerShell script reports failure.
PowerShell
Copy
```
dotnet run
if ($LastExitCode -eq 0) {
Write-Host "Execution succeeded"
} else
{
Write-Host "Execution Failed"
}
Write-Host "Return value = " $LastExitCode
```
Output
Copy
```
Execution succeeded
Return value = 0
```
### Async Main return values
When you declare an `async` return value for `Main`, the compiler generates the boilerplate code for calling asynchronous methods in `Main`:
C\#
Copy
```
class Program
{
static async Task<int> Main(string[] args)
{
return await AsyncConsoleWork();
}
private static async Task<int> AsyncConsoleWork()
{
return 0;
}
}
```
In both examples, the main body of the program is within the body of the `AsyncConsoleWork()` method.
An advantage of declaring `Main` as `async` is that the compiler always generates the correct 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 of `private static void $GeneratedMain() => Main().GetAwaiter().GetResult();`.
- `static Task Main(string[])` results in the compiler emitting the equivalent of `private static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();`.
- `static Task<int> Main()` results in the compiler emitting the equivalent of `private static int $GeneratedMain() => Main().GetAwaiter().GetResult();`.
- `static Task<int> Main(string[])` results in the compiler emitting the equivalent of `private static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();`.
Note
If the examples use the `async` modifier on the `Main` method, the compiler generates the same code.
## Command-line arguments
You can send arguments to the `Main` method by defining the method in one of the following ways:
Expand table
| `Main` declaration | `Main` method code |
|---|---|
| `static void Main(string[] args)` | No return value or `await` |
| `static int Main(string[] args)` | Returns a value but doesn't use `await` |
| `static async Task Main(string[] args)` | Uses `await` but doesn't return a value |
| `static async Task<int> Main(string[] args)` | Return a value and uses `await` |
If you don't use the arguments, you can omit `args` from the method declaration for slightly simpler code:
Expand table
| `Main` declaration | `Main` method code |
|---|---|
| `static void Main()` | No return value or `await` |
| `static int Main()` | Returns a value but doesn't use `await` |
| `static async Task Main()` | Uses `await` but doesn't return a value |
| `static async Task<int> Main()` | Returns a value and uses `await` |
Note
You can also use [Environment.CommandLine](https://learn.microsoft.com/en-us/dotnet/api/system.environment.commandline) or [Environment.GetCommandLineArgs](https://learn.microsoft.com/en-us/dotnet/api/system.environment.getcommandlineargs) to access the command-line arguments from any point in a console or Windows Forms application. To enable command-line arguments in the `Main` method declaration in a Windows Forms application, you must manually modify the declaration of `Main`. The code generated by the Windows Forms designer creates `Main` without an input parameter.
The parameter of the `Main` method is a [String](https://learn.microsoft.com/en-us/dotnet/api/system.string) array that represents the command-line arguments. Usually, you determine whether arguments exist by testing the `Length` property, for example:
C\#
Copy
```
if (args.Length == 0)
{
System.Console.WriteLine("Please enter a numeric argument.");
return 1;
}
```
Tip
The `args` array can't be null. So, it's safe to access the `Length` property without null checking.
You can also convert the string arguments to numeric types by using the [Convert](https://learn.microsoft.com/en-us/dotnet/api/system.convert) class or the `Parse` method. For example, the following statement converts the `string` to a `long` number by using the [Parse](https://learn.microsoft.com/en-us/dotnet/api/system.int64.parse) method:
C\#
Copy
```
long num = Int64.Parse(args[0]);
```
It's also possible to use the C\# type `long`, which aliases `Int64`:
C\#
Copy
```
long num = long.Parse(args[0]);
```
You can also use the `Convert` class method `ToInt64` to do the same thing:
C\#
Copy
```
long num = Convert.ToInt64(s);
```
For more information, see [Parse](https://learn.microsoft.com/en-us/dotnet/api/system.int64.parse) and [Convert](https://learn.microsoft.com/en-us/dotnet/api/system.convert).
Tip
Parsing command-line arguments can be complex. Consider using the [System.CommandLine](https://learn.microsoft.com/en-us/dotnet/standard/commandline/) library 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:
1. Paste the following code into any text editor, and then save the file as a text file with the name *Factorial.cs*.
C\#
Copy
```
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 the `Main` method, the program tests if input arguments weren't supplied by comparing the length of the `args` argument to `0` 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 in `result` variable of type `long`), the verbose result is printed depending on the `result` variable.
1. From the **Start** screen or **Start** menu, open a Visual Studio **Developer Command Prompt** window, and then navigate to the folder that contains the file that you created.
2. To compile the application, enter the following command:
`dotnet build`
If your application has no compilation errors, the build process creates a binary file named *Factorial.dll*.
3. Enter the following command to calculate the factorial of 3:
`dotnet run -- 3`
4. If you enter 3 on the command line as the program's argument, the output reads: `The factorial of 3 is 6.`
Note
When running an application in Visual Studio, specify command-line arguments in the [Debug Page, Project Designer](https://learn.microsoft.com/en-us/visualstudio/ide/reference/debug-page-project-designer).
## C\# language specification
For more information, see the [C\# Language Specification](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/readme). The language specification is the definitive source for C\# syntax and usage.
## See also
- [System.Environment](https://learn.microsoft.com/en-us/dotnet/api/system.environment)
- [How to display command line arguments](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/how-to-display-command-line-arguments)
Collaborate with us on GitHub
The source for this content can be found on GitHub, where you can also create and review issues and pull requests. For more information, see [our contributor guide](https://learn.microsoft.com/contribute/content/dotnet/dotnet-contribute).
 
.NET feedback
.NET is an open source project. Select a link to provide feedback:
[Open a documentation issue](https://github.com/dotnet/docs/issues/new?template=z-customer-feedback.yml&pageUrl=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fdotnet%2Fcsharp%2Ffundamentals%2Fprogram-structure%2Fmain-command-line&pageQueryParams=&contentSourceUrl=https%3A%2F%2Fgithub.com%2Fdotnet%2Fdocs%2Fblob%2Fmain%2Fdocs%2Fcsharp%2Ffundamentals%2Fprogram-structure%2Fmain-command-line.md&documentVersionIndependentId=d942d65a-87e4-1525-bd94-b005f1b7cbac&platformId=b5f2b93f-6542-e3a0-a56e-c7ffade6f6c2&feedback=%0A%0A%5BEnter+feedback+here%5D%0A&author=%40BillWagner&metadata=*+ID%3A+06ef4bd7-7012-8afd-721a-a4c31db20202%0A*+PlatformId%3A+b5f2b93f-6542-e3a0-a56e-c7ffade6f6c2+%0A*+Service%3A+**dotnet-csharp**%0A*+Sub-service%3A+**fundamentals**) [Provide product feedback](https://aka.ms/feedback/report?space=61)
***
## Feedback
Was this page helpful?
Yes
No
No
Need help with this topic?
Want to try using Ask Learn to clarify or guide you through this topic?
Ask Learn
Ask Learn
Suggest a fix?
***
## Additional resources
Training
Learning path
[Create methods in C\# console applications (Get started with C\#, Part 5) - Training](https://learn.microsoft.com/en-us/training/paths/get-started-c-sharp-part-5/?source=recommendations)
This learning path covers the syntax of creating and using methods in C\# console applications.
***
- Last updated on
12/15/2025
## In this article
1. [Overview](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#overview)
2. [Main() return values](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#main-return-values)
3. [Command-line arguments](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#command-line-arguments)
4. [C\# language specification](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#c-language-specification)
5. [See also](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#see-also)
Was this page helpful?
Yes
No
No
Need help with this topic?
Want to try using Ask Learn to clarify or guide you through this topic?
Ask Learn
Ask Learn
Suggest a fix?
## Ask Learn
Preview
Ask Learn is an AI assistant that can answer questions, clarify concepts, and define terms using trusted Microsoft documentation.
Please sign in to use Ask Learn.
[Sign in](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line)
[English (United States)](https://learn.microsoft.com/en-us/locale?target=https%3A%2F%2Flearn.microsoft.com%2Fen-us%2Fdotnet%2Fcsharp%2Ffundamentals%2Fprogram-structure%2Fmain-command-line)
[Your Privacy Choices](https://aka.ms/yourcaliforniaprivacychoices)
Theme
- Light
- Dark
- High contrast
- [AI Disclaimer](https://learn.microsoft.com/en-us/principles-for-ai-generated-content)
- [Previous Versions](https://learn.microsoft.com/en-us/previous-versions/)
- [Blog](https://techcommunity.microsoft.com/t5/microsoft-learn-blog/bg-p/MicrosoftLearnBlog)
- [Contribute](https://learn.microsoft.com/en-us/contribute)
- [Privacy](https://go.microsoft.com/fwlink/?LinkId=521839)
- [Terms of Use](https://learn.microsoft.com/en-us/legal/termsofuse)
- [Trademarks](https://www.microsoft.com/legal/intellectualproperty/Trademarks/)
- © Microsoft 2026 |
| Readable Markdown | The runtime calls the `Main` method when you start a C\# application. The `Main` method is the entry point of a C\# application.
A C\# program can have only one entry point. If you have more than one class with a `Main` method, you must use the **StartupObject** compiler option when you compile your program to specify which `Main` method serves as the entry point. For more information, see [**StartupObject** (C\# Compiler Options)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/advanced#startupobject). 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. Like the `Main` method, top-level statements can [return values](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#main-return-values) and access [command-line arguments](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line#command-line-arguments). For more information, see [Top-level statements](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements). The following example uses a `foreach` loop to display the command-line arguments by using the `args` 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 be [*file-based apps*](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/#building-and-running-c-programs), where a single file contains the program. You run *file-based apps* by using the command `dotnet <file.cs>`, or by using the `#!/usr/bin/env dotnet run` directive as the first line (Unix shells only).
- The `Main` method is the entry point of an executable program. It's where the program control starts and ends.
- You must declare `Main` inside a class or struct. The enclosing `class` can be `static`.
- `Main` must be [`static`](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/static).
- `Main` can have any [access modifier](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/access-modifiers).
- `Main` can return `void`, `int`, `Task`, or `Task<int>`.
- If and only if `Main` returns a `Task` or `Task<int>`, the declaration of `Main` can include the [`async`](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/async) modifier. This rule specifically excludes an `async void Main` method.
- You can declare the `Main` method with or without a `string[]` parameter that contains command-line arguments. When using Visual Studio to create Windows applications, you can add the parameter manually or else use the [GetCommandLineArgs()](https://learn.microsoft.com/en-us/dotnet/api/system.environment.getcommandlineargs#system-environment-getcommandlineargs) method to obtain the command-line arguments. Parameters are zero-indexed command-line arguments. Unlike C and C++, the name of the program isn't treated as the first command-line argument in the `args` array, but it's the first element of the [GetCommandLineArgs()](https://learn.microsoft.com/en-us/dotnet/api/system.environment.getcommandlineargs#system-environment-getcommandlineargs) method.
The following list shows the most common `Main` 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 implicitly `private` by default. You can specify any explicit access modifier.
Tip
By using `async` and `Task` or `Task<int>` return types, you simplify program code when console applications need to start and `await` asynchronous operations in `Main`.
You can return an `int` from the `Main` method by defining the method in one of the following ways:
| `Main` declaration | `Main` method code |
|---|---|
| `static int Main()` | No use of `args` or `await` |
| `static int Main(string[] args)` | Uses `args` but not `await` |
| `static async Task<int> Main()` | Uses `await` but not `args` |
| `static async Task<int> Main(string[] args)` | Uses `args` and `await` |
If the return value from `Main` isn't used, returning `void` or `Task` allows for slightly simpler code.
| `Main` declaration | `Main` method code |
|---|---|
| `static void Main()` | No use of `args` or `await` |
| `static void Main(string[] args)` | Uses `args` but not `await` |
| `static async Task Main()` | Uses `await` but not `args` |
| `static async Task Main(string[] args)` | Uses `args` and `await` |
However, returning `int` or `Task<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](https://learn.microsoft.com/en-us/dotnet/core/introduction) command-line tools. If you're unfamiliar with .NET Core command-line tools, you can learn about them in this [get-started article](https://learn.microsoft.com/en-us/dotnet/core/tutorials/create-console-app).
Create a new application by running `dotnet new console`. Modify the `Main` method in *Program.cs* as follows:
```
class MainReturnValTest
{
static int Main()
{
//...
return 0;
}
}
```
Remember to save this program as *MainReturnValTest.cs*.
When you execute a program in Windows, the system stores any value returned from the `Main` function in an environment variable. You can retrieve this environment variable by using `ERRORLEVEL` from a batch file, or `$LastExitCode` from PowerShell.
You can build the application by using the [dotnet CLI](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet) `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 reports success. However, if you change MainReturnValTest.cs to return a nonzero value and then recompile the program, subsequent execution of the PowerShell script reports failure.
```
dotnet run
if ($LastExitCode -eq 0) {
Write-Host "Execution succeeded"
} else
{
Write-Host "Execution Failed"
}
Write-Host "Return value = " $LastExitCode
```
```
Execution succeeded
Return value = 0
```
When you declare an `async` return value for `Main`, the compiler generates the boilerplate code for calling asynchronous methods in `Main`:
```
class Program
{
static async Task<int> Main(string[] args)
{
return await AsyncConsoleWork();
}
private static async Task<int> AsyncConsoleWork()
{
return 0;
}
}
```
In both examples, the main body of the program is within the body of the `AsyncConsoleWork()` method.
An advantage of declaring `Main` as `async` is that the compiler always generates the correct 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 of `private static void $GeneratedMain() => Main().GetAwaiter().GetResult();`.
- `static Task Main(string[])` results in the compiler emitting the equivalent of `private static void $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();`.
- `static Task<int> Main()` results in the compiler emitting the equivalent of `private static int $GeneratedMain() => Main().GetAwaiter().GetResult();`.
- `static Task<int> Main(string[])` results in the compiler emitting the equivalent of `private static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();`.
Note
If the examples use the `async` modifier on the `Main` method, the compiler generates the same code.
You can send arguments to the `Main` method by defining the method in one of the following ways:
| `Main` declaration | `Main` method code |
|---|---|
| `static void Main(string[] args)` | No return value or `await` |
| `static int Main(string[] args)` | Returns a value but doesn't use `await` |
| `static async Task Main(string[] args)` | Uses `await` but doesn't return a value |
| `static async Task<int> Main(string[] args)` | Return a value and uses `await` |
If you don't use the arguments, you can omit `args` from the method declaration for slightly simpler code:
| `Main` declaration | `Main` method code |
|---|---|
| `static void Main()` | No return value or `await` |
| `static int Main()` | Returns a value but doesn't use `await` |
| `static async Task Main()` | Uses `await` but doesn't return a value |
| `static async Task<int> Main()` | Returns a value and uses `await` |
Note
You can also use [Environment.CommandLine](https://learn.microsoft.com/en-us/dotnet/api/system.environment.commandline) or [Environment.GetCommandLineArgs](https://learn.microsoft.com/en-us/dotnet/api/system.environment.getcommandlineargs) to access the command-line arguments from any point in a console or Windows Forms application. To enable command-line arguments in the `Main` method declaration in a Windows Forms application, you must manually modify the declaration of `Main`. The code generated by the Windows Forms designer creates `Main` without an input parameter.
The parameter of the `Main` method is a [String](https://learn.microsoft.com/en-us/dotnet/api/system.string) array that represents the command-line arguments. Usually, you determine whether arguments exist by testing the `Length` property, for example:
```
if (args.Length == 0)
{
System.Console.WriteLine("Please enter a numeric argument.");
return 1;
}
```
Tip
The `args` array can't be null. So, it's safe to access the `Length` property without null checking.
You can also convert the string arguments to numeric types by using the [Convert](https://learn.microsoft.com/en-us/dotnet/api/system.convert) class or the `Parse` method. For example, the following statement converts the `string` to a `long` number by using the [Parse](https://learn.microsoft.com/en-us/dotnet/api/system.int64.parse) method:
```
long num = Int64.Parse(args[0]);
```
It's also possible to use the C\# type `long`, which aliases `Int64`:
```
long num = long.Parse(args[0]);
```
You can also use the `Convert` class method `ToInt64` to do the same thing:
```
long num = Convert.ToInt64(s);
```
For more information, see [Parse](https://learn.microsoft.com/en-us/dotnet/api/system.int64.parse) and [Convert](https://learn.microsoft.com/en-us/dotnet/api/system.convert).
Tip
Parsing command-line arguments can be complex. Consider using the [System.CommandLine](https://learn.microsoft.com/en-us/dotnet/standard/commandline/) library 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:
1. Paste the following code into any text editor, and then save the file as a text file with the name *Factorial.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 the `Main` method, the program tests if input arguments weren't supplied by comparing the length of the `args` argument to `0` 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 in `result` variable of type `long`), the verbose result is printed depending on the `result` variable.
1. From the **Start** screen or **Start** menu, open a Visual Studio **Developer Command Prompt** window, and then navigate to the folder that contains the file that you created.
2. To compile the application, enter the following command:
`dotnet build`
If your application has no compilation errors, the build process creates a binary file named *Factorial.dll*.
3. Enter the following command to calculate the factorial of 3:
`dotnet run -- 3`
4. If you enter 3 on the command line as the program's argument, the output reads: `The factorial of 3 is 6.`
For more information, see the [C\# Language Specification](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/readme). The language specification is the definitive source for C\# syntax and usage.
- [System.Environment](https://learn.microsoft.com/en-us/dotnet/api/system.environment)
- [How to display command line arguments](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/how-to-display-command-line-arguments) |
| Shard | 168 (laksa) |
| Root Hash | 14615152987638977768 |
| Unparsed URL | com,microsoft!learn,/en-us/dotnet/csharp/fundamentals/program-structure/main-command-line s443 |