Top-level statements in C# 9.0

Alex Tumanoff
5 min readMar 5, 2021
Photo by Fotis Fotopoulos on Unsplash

Each new version of C# gives us a lot of possibilities. C# 9.0 does the same. In this article, we will talk about a new feature from C# 9.0: top-level statements. Let’s start our deep diving.

A typical scratch console application looks like this:

There is no magic. Everything as usual: namespace, class, method Main. I believe you saw it many times.

What is the problem with this? It is a little bit wordy. To print “Hello, World!” we need to create a namespace, class, and method. C# 9.0 allows us to shorten this code. The mechanism for it is called top-level statements. It is very simple to use. Instead of using namespaces, classes, and the Main method you write statements at the top level of the file. Let’s modify our base app with top-level statements:

As you can see there are no namespace, class, and Main method. Right now there is only code for printing “Hello, World!”.

Please remember that top-level statements are available since C# 9.0 and .NET 5.0. If you want to work with it you should have Visual Studio 2019 16.8 and above. You can check the version of your VS 2019 in the menu: Help->About Microsoft Visual Studio.

If you click on About item you’ll see the window with information about VS 2019:

Also, you need to set the version of the framework for your project to .NET 5.0. You can do it in two ways. The first one is to click on menu item Project->name_of_Project Properties:

After a click, you’ll see the window where you can choose the version of the framework:

Another way is to click on the name of your project in Solution Explorer and modify the version in file with project settings:

Time to come back to our top-level statements. What else can be done with such an approach? Everything, that you need. In the next example, we will calculate the maximum from two variables.

In the code above we created the method GetMaximum and passed 2 parameters to it. With top-level statements, we can create as many methods as we want. Methods can be placed in any place, not only at the end of the file. For example:

We placed GetMaximum above its call, but nothing has changed. Everything will work as it was before. An important point to pay attention to is the scope. Each method sees all global variables that were declared before.

Method GetMaximum sees all global variables declared above and because of this we can use variables first and second without passing them. Of course, it is not a good idea to code like this, but you should know that such a way exists.

Can we declare namespaces and classes inside the file with top-level statements? Yes, we can, but it should be done after all top-level statements.

In this example, we have namespace MyNameSpace with class A inside it and class Book. This code works fine, but if we place these declarations above any top-level statement, we will get a compile error. The next code won’t compile, because of this error.

This code won’t compile and run because MyNamespace is declared above top-level statements (creation of Book object and console output).

Maybe some of you right now think: “Ok, but how to use command-line arguments? Where is args array?” And here comes some magic. You can use the args array in top-level statements because it exists even we didn’t declare it. Here is how to work with it:

Nothing unusual, except that args come from somewhere, but we can live with that.

One more important point: only one file in your project can contain top-level statements. It does not matter which name this file has. So top-level statements can be in Program.cs or somewhere else, but only in one file.

Extra part

As developers, we shouldn’t believe in magic. The main question for us: What really happens when we use top-level statements instead of the typical Main method? What is inside our MSIL code?

Let’s analyze the last example:

You can analyze the MSIL code of your application with different tools. I prefer dotPeek from JetBrains.

As you see nothing magical happens. Our top-level statements were included inside the Main method in MSIL code.

Summary

When and why we can use top-level statements? I believe it is a good mechanism to test something quickly. Maybe you don’t have a lot of code in your application and top-level statements are a choice for you.

Is it a good way for beginners to start study C#? I am not pretty sure, because it is not a big deal to explain the Main approach to someone new.

Time will show how top-level statements are.

--

--