• Pedro Rubio
learn development C#

In this article we want to take a look at a new feature coming with C# 9.0 called Top-level programs, that significantly simplifies certain C# programs. In a few words: there is less code that you need to write to get something actually functioning, which is always great.

We are going to walk through a few of the useful things that you can do with top-level programs and how to get started.

Initial setup

As top-level programs is a C# 9 feature we need to target a framework that includes that version of the language; .NET 5.0 (still in RC version at the moment of writing this article) will work for us.

From an empty folder let's run the following command to create our project:

dotnet new console -f net5.0

The command line tool will generate a Program.cs file with the basic scaffolding for a console app:

using System;

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

Creating the most simple program in C#

Now is when the magic happens... Let's simplify the previous program, so the content of the Program.cs file should have only the following sentence:

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

So if we run our console app with:

dotnet run

We'll get the expected output:

 Hello World

That probably was the simplest fully functioning C# you've seen in your life! You might be wondering where is all the boilerplate code we've always needed: namespace and class declarations, static main method with arguments, etc. We simply don't need it with top-level programs!

When our one-liner C# program is compiled, the compiler generates the Program class and also the Main method, so behind the scenes it's like if we had the original program at the beginning of the article. That makes our life easier as developers as the compiler gets the job done for us.

Adding functionality to our program

Let's play with our program by just adding a bit of complexity to see what we can implement with top-level programs:

Command line arguments

Console apps often receive command line arguments in an array of strings. Our simple program could get the message that will be shown as a command line argument, so we could modify it to be:


The following execution will produce exactly the same output we got before:

dotnet run -- "Hello World"


What if we wanted to have some functions in our program? We can add a simple one to process our message before printing it out; let's also add back the using statement for those who miss it:

using System;

string Transform(string message) => message.ToUpper();

var message = Transform(args[0]);

The same execution of the program with the "Hello World" argument will produce now:


Asynchronous code

Asynchronous code is one of the most popular features in C# since it was introduced in C# 5. We can use the await keyword directly in our program if, for example, we want to delay for 3 seconds the output we generate:

using System;
using System.Threading.Tasks;

string Transform(string message) => message.ToUpper();

var message = Transform(args[0]);
await Task.Delay(3000);


Top-level programs are perfect when writing simple utility applications that don't have much code, so the compiler will generate the main method and class for us. They also add to C# the ability to create scripts in a simple and quick manner, in the same way we create them in other scripting languages such us Python or JavaScript that are designed for that purpose.

Liked this post? Share it!
About Pedro Rubio

More than 15 years of experience in the Software Industry. Focused on adding value to customers and products with teams made up of the best professionals. He loves video games and travelling.