3 options:
- You can return it from
Main
if you declare your Main
method to return int
.
- You can call
Environment.Exit(code)
.
- You can set the exit code using properties:
Environment.ExitCode = -1;
. This will be used if nothing else sets the return code or uses one of the other options above).
Depending on your application (console, service, web app, etc) different methods can be used.
Access modifiers
From docs.microsoft.com:
public
The type or member can be accessed by any other code in the same assembly or another assembly that references it.
private
The type or member can only be accessed by code in the same class or struct.
protected
The type or member can only be accessed by code in the same class or struct, or in a derived class.
private protected
(added in C# 7.2)
The type or member can only be accessed by code in the same class or struct, or in a derived class from the same assembly, but not from another assembly.
internal
The type or member can be accessed by any code in the same assembly, but not from another assembly.
protected internal
The type or member can be accessed by any code in the same assembly, or by any derived class in another assembly.
When no access modifier is set, a default access modifier is used. So there is always some form of access modifier even if it's not set.
The static modifier on a class means that the class cannot be instantiated, and that all of its members are static. A static member has one version regardless of how many instances of its enclosing type are created.
A static class is basically the same as a non-static class, but there is one difference: a static class cannot be externally instantiated. In other words, you cannot use the new keyword to create a variable of the class type. Because there is no instance variable, you access the members of a static class by using the class name itself.
However, there is a such thing as a static constructor. Any class can have one of these, including static classes. They cannot be called directly & cannot have parameters (other than any type parameters on the class itself). A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced. Looks like this:
static class Foo()
{
static Foo()
{
Bar = "fubar";
}
public static string Bar { get; set; }
}
Static classes are often used as services, you can use them like so:
MyStaticClass.ServiceMethod(...);
Best Answer
As you discovered, in VS11 the compiler will disallow an
async Main
method. This was allowed (but never recommended) in VS2010 with the Async CTP.I have recent blog posts about async/await and asynchronous console programs in particular. Here's some background info from the intro post:
Here's why this is a problem in Console programs with an
async Main
:One solution is to provide your own context - a "main loop" for your console program that is async-compatible.
If you have a machine with the Async CTP, you can use
GeneralThreadAffineContext
from My Documents\Microsoft Visual Studio Async CTP\Samples(C# Testing) Unit Testing\AsyncTestUtilities. Alternatively, you can useAsyncContext
from my Nito.AsyncEx NuGet package.Here's an example using
AsyncContext
;GeneralThreadAffineContext
has almost identical usage:Alternatively, you can just block the main Console thread until your asynchronous work has completed:
Note the use of
GetAwaiter().GetResult()
; this avoids theAggregateException
wrapping that happens if you useWait()
orResult
.Update, 2017-11-30: As of Visual Studio 2017 Update 3 (15.3), the language now supports an
async Main
- as long as it returnsTask
orTask<T>
. So you can now do this:The semantics appear to be the same as the
GetAwaiter().GetResult()
style of blocking the main thread. However, there's no language spec for C# 7.1 yet, so this is only an assumption.