One of the major complain you can make about C# is that it's a very verbose language. To bootstrap a simple Hello World, you need 12 lines of code!!!

using System;

namespace csharp9
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

With the rise of new languages like Python and F# that have lighter syntax, Microsoft knows it has to make some changes to keep C# in the game. I mean, C# is not going anywhere, but it's just better if the developers are happy with it and praise it everywhere. With that in mind, C# 9.0 is bringing the first steps toward a simpler syntax for the Main method, aka Top-Level program.

You can now write the same Hello World with two lines! That's more like it.

using System;
Console.WriteLine("Hello World!");

Isn't it beautiful? Under the cover, the C# compiler will generate all the required boilerplate code to make your program execute just like before.

csharp9-console-app-still-working

This feature is only available on the preview of C# 9.0, look at this blog post to learn all about the C# 9.0 preview and how to install it.

Arguments

Ok, so it works fine with a simple Hello World, but is it viable in a real-world scenario? What happens if my program takes arguments through the args parameter?
Fortunately, it's supported through a magic kinda-global variable args that always exist in the scope of the program.cs file. You don't need to declare it; you can use it directly as if it was coming from Main(string[] args).

csharp9-args

Async

Since C# 7.1, it's also possible to make your Main method async and return a Task or Task<T>.

static async Task<int> Main()
{
    return await DoAsyncWork();
}

How does that translate in C# 9.0?

using System;

var service = new AsyncService();
var result = await service.MyAsyncMethod();
Console.WriteLine($"Hello {result}!");

Throw an await in there, and it just works out of the box, with no special instructions or weird syntax keywords.

Return codes

The last thing that comes to mind if I try to break the new auto-magic Main is the return codes. Some programs use a return code to hint the caller about the result of the execution. Usually, 0 is used for success, and 1 for errors.

using System;

Console.WriteLine($"Hello world!");
return 1;

csharp9-code1

It seems like that part also works as expected. There's not much to add here.

Put it all together

var s = new AsyncService();
var result = await s.MyAsyncMethod();
Console.WriteLine($"Hello {args[0]}! result: {result}");
return 1;

Here's an example that tries to combine everything at once. I'm fascinated to see how smoothly this feature is working. I have always been a big fan of F#'s minimalistic syntax, and I'm happy to see some concepts shifting to C#.

You can find all the code samples on my github repo