Table of contents >> Objects > Top level statements
Low importance article, or discussion

C# 9 introduced a new feature called top level statements, which allow us to write code without explicitly defining a Main() method or a containing class. For example, a simple "Hello, World!" program that we used to write like this:

1
2
3
4
5
6
7
8
9
10
11
12
using System;
 
namespace MyProject
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

can now be written with top level statements like this:

1
Console.WriteLine("Hello World!");

While this looks neat, there are a few drawbacks of which I will discuss later on. But first, where do you find these? Well, obviously, you will need to use at least C# version 9, since that's when they were introduced. You also need to use at least .NET 5, so, they will not be available if you create a console project for .NET Framework, which is older, for instance.

From start you should be aware that it may not look so, but there's a hidden Main() method and a compiler-generated Program class behind the scenes. The compiler takes your top-level statements and implicitly wraps them within a synthetic Main() method.

So, yes, the one-line code for writing a text at the console that I just showed you? It is actually converted by the compiler exactly into the first example, where that line is inside a Main() method, in a Program class.

Does this mean you can't use methods? What a useless feature!

Actually, you can. You can write code like this:

1
2
3
4
5
6
void PrintText(string text)
{
    Console.WriteLine(text);
}
 
PrintText("Hello World!");

which then it is converted by the compiler into this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System;
 
namespace MyProject
{
    class Program
    {
        static void Main(string[] args)
        {
            void PrintText(string text)
            {
                Console.WriteLine(text);
            }
            
            PrintText("Hello World!");
        }
    }
}

You probably already recognized the use of a local method, because the PrintText() method is declared inside the Main() method.

And here, the good part ends, and the drawbacks begin:

  • you cannot directly access the Main() method or the generated Program class, which might be needed in some cases, like unit testing.
  • you cannot overload your methods, and especially for an unexperienced programmer, this can be really confusing and discouraging.
  • there is hidden complexity, the program works, and it is not immediately obvious to the programmer as to how it does so.
  • inconsistency: an application can only have a single entry point, which means that if you use top level statements in multiple files, multiple Main() methods would be generated, and you will get a compiler error. This means that most of your project will still have to use the old C# structure, while your entry point file would follow a different style, of top level statements. This only generates confussion and it's hard to follow.
  • top level statements were introduced only as a Microsoft hype of trying to emulate Python, where you can write to the standard output using a single line of code. While this might be nice, C# is not Python, and Microsoft should stop trying to make it look or behave like other languages. In the end, Python doesn't copy C#, and it's doing quite well. Add to this the fact that it is well known that Microsoft quicly abbandons their hypes, and you will start seeing top level statements as what they are: no more than feature that falls short for anything else other than toy console programs (by the way, this is just my personal oppinion, you can still do as you please).

Top level statements are not enabled by default when creating a Console application. You can enable or disable them by unchecking the "Do not use top-level statements" option in Visual Studio, when creating a new Console App project. If the project is already created and top level statements were enabled, you can only change this by creating a Main() method in a Program class, manually.