Skip to content

Conversation

BillWagner
Copy link
Member

Fixes #2795

/cc @stephentoub

[Inside a C# Program](../../../csharp/programming-guide/inside-a-program/index.md)
[\<paveover>C# Sample Applications](http://msdn.microsoft.com/en-us/9a9d7aaa-51d3-4224-b564-95409b0f3e15)
# Main() and command-line arguments (C# Programming Guide)
The `Main` method is the entry point of a C# console application or windows application. (Libraries and services do not require a `Main` method as an entry point.). When the application is started, the `Main` method is the first method that is invoked.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than "console application or windows application", should we just say "executable application" or something like that? Is "windows" here meant to refer to the OS or to an application that has "windows"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

## Overview

- The `Main` method is the entry point of an .exe program; it is where the program control starts and ends.
- `Main` is declared inside a class or struct. `Main` must be [static](../../../csharp/language-reference/keywords/static.md) and it should not be [public](../../../csharp/language-reference/keywords/public.md). (In the earlier example, it receives the default access of [private](../../../csharp/language-reference/keywords/private.md).) The enclosing class or struct is not required to be static.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and it should not be public

It doesn't need to be public, but why shouldn't it be public?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Note: I looked through old versions of the C# Spec, and this was never true, and never part of the spec. I wonder how this snuck through in this content (because it has been there for quite a while)

- The `Main` method is the entry point of an .exe program; it is where the program control starts and ends.
- `Main` is declared inside a class or struct. `Main` must be [static](../../../csharp/language-reference/keywords/static.md) and it should not be [public](../../../csharp/language-reference/keywords/public.md). (In the earlier example, it receives the default access of [private](../../../csharp/language-reference/keywords/private.md).) The enclosing class or struct is not required to be static.
- `Main` can either have a `void`, `int`, `Task`, or `Task<int>` return type.
- If and only if `Main` returns a `Task` or `Task<int>`, the declaration of `Main` may include the [`async`](../../language-reference/keywords/async.md) modifier. Note that this specifically excludes an `async void Main` method.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If and only if

Technically this isn't correct (the "only if" is correct, but not the "if"). It's valid to have, e.g.

static Task Main() => Task.CompletedTask;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I take back my correctness comment. You say "may include", so that's fine.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😄


!code-cs[csProgGuideMain#13](../../../csharp/programming-guide/inside-a-program/codesnippet/CSharp/main-return-values_2.cs)]

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 following example shows how the return value from `Main` can be accessed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's be worth explicitly stating that the returned value is treated as the exit code for the process.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

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:

```csharp
public static void Main()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc earlier explicitly stated that Main shouldn't be public (and I commented on why it was making that guidance), but here it's public 😄

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦‍♂️

[\<paveover>C# Sample Applications](http://msdn.microsoft.com/en-us/9a9d7aaa-51d3-4224-b564-95409b0f3e15)
# Main() and command-line arguments (C# Programming Guide)

The `Main` method is the entry point of a C# application. (Libraries and services do not require a `Main` method as an entry point.). When the application is started, the `Main` method is the first method that is invoked.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra period in "point.)."

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

- If and only if `Main` returns a `Task` or `Task<int>`, the declaration of `Main` may include the [`async`](../../language-reference/keywords/async.md) modifier. Note that this specifically excludes an `async void Main` method.
- The `Main` method can be declared with or without a `string[]` parameter that contains command-line arguments. When using [!INCLUDE[vsprvs](~/includes/vsprvs-md.md)] to create Windows applications, you can add the parameter manually or else use the <xref:System.Environment> class to obtain the command-line arguments. Parameters are read as zero-indexed command-line arguments. Unlike C and C++, the name of the program is not treated as the first command-line argument.

The addition of `async` and `Task`, `Task<int>` returns types is only available with C# 7.1 and higher. This feature simplifies program code when console applications need to start and `await` asyncnhronous operations in `Main`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: asyncnhronous --> asynchronous
But see comment above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.


- The `Main` method is the entry point of an executable program; it is where the program control starts and ends.
- `Main` is declared inside a class or struct. `Main` must be [static](../../../csharp/language-reference/keywords/static.md) and it need not be [public](../../../csharp/language-reference/keywords/public.md). (In the earlier example, it receives the default access of [private](../../../csharp/language-reference/keywords/private.md).) The enclosing class or struct is not required to be static.
- `Main` can either have a `void`, `int`, `Task`, or `Task<int>` return type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd mention the C# version here, not later where it's likely to be overlooked: "Main can either have a void, int, or, starting with C# 7.1, a Task or a Task<int> return type."

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

[C# Programming Guide](../../../csharp/programming-guide/index.md)
[Methods](../../../csharp/programming-guide/classes-and-structs/methods.md)
[Inside a C# Program](../../../csharp/programming-guide/inside-a-program/index.md)
[\<paveover>C# Sample Applications](http://msdn.microsoft.com/en-us/9a9d7aaa-51d3-4224-b564-95409b0f3e15)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be deleted.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


[!code-cs[csProgGuideMain#14](../../../csharp/programming-guide/inside-a-program/codesnippet/CSharp/main-return-values_3.cs)]

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 from `$LastExitCode` from powershell.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

better: "using ERRORLEVEL from a batch file or $LastExitCode from Powershell."

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.


## Compiler generated code

When the application entry point does return a `Task` or `Task<int>` The compiler will generate a new entry point that will call the entry point method declared in the application code. If you imagine that this entry point is called `$GeneratedMain`, the new allowed signatures will behave as follows:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does return --> returns
comma before "The compiler", and lowercase "the"
will generate --> generates
will call --> calls
If you imagine --> Assuming
"the new allowed signatures will behave" is an awkward phrase; I'm not sure what it means.


When the application entry point does return a `Task` or `Task<int>` The compiler will generate a new entry point that will call the entry point method declared in the application code. If you imagine that this entry point is called `$GeneratedMain`, the new allowed signatures will behave as follows:

- `static Task Main()` will result in the compiler emitting the equivalent of private `static void $GeneratedMain() => Main().GetAwaiter().GetResult();`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In each of these cases, it's best to use present rather than future tense.
private should also be fenced

- `static Task<int> Main(string[])` will result in the compiler emitting the equivalent of `private static int $GeneratedMain(string[] args) => Main(args).GetAwaiter().GetResult();`

> [!NOTE]
> The above examples could all have the `async` modifier on the `Main` method and would generate the same resulting code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somewhat clearer, perhaps: If the examples all used the async modifier on the Main method, the compiler would generate the same code.

Thanks @rpetrusha.  I've addressed all the concerns.
Copy link
Contributor

@rpetrusha rpetrusha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I didn't notice: on line 60, "returns types" --> "return types". Otherwise, LGTM, @BillWagner, and this will be ready to merge when you want.

@BillWagner BillWagner merged commit d019d1c into dotnet:master Aug 3, 2017
@BillWagner BillWagner deleted the updates-for-async-Main branch August 3, 2017 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants