Take advantage of the new top-level statements in C# 9.0 to eliminate boilerplate code and make your programs more readable, maintainable, and efficient. Credit: SwissMediaVision / Getty Images When writing programs in the C# programming language, you invariably need to write a lot of boilerplate code — even for simple console applications. Imagine that you want to write some code to test whether a library or an API is functioning properly. You might write a console application to accomplish this, but you’re nonetheless constrained to follow standard C# semantics. You must write your code inside the Main method. Top-level programs, a new concept introduced in C# 9.0, allow you to write code for simple programs sans the need to write boilerplate code. Top-level programs are a great new feature that allows you to write cleaner, shorter, and simpler code. You can take advantage of top-level programs to explore new ideas. This article discusses how you can work with top-level programs in C# 9.0. To work with the code examples provided in this article, you should have Visual Studio 2019 installed in your system. If you don’t already have a copy, you can download Visual Studio 2019 here. Note that C# 9.0 is available in Visual Studio 2019 version 16.9 Preview 1 or later, and in the .NET 5.0 SDK. Create a .NET Core console application project in Visual Studio First off, let’s create a .NET Core console application project in Visual Studio. Assuming Visual Studio 2019 is installed in your system, follow the steps outlined below to create a new .NET Core console application project in Visual Studio. Launch the Visual Studio IDE. Click on “Create new project.” In the “Create new project” window, select “Console App (.NET Core)” from the list of templates displayed. Click Next. In the “Configure your new project” window, specify the name and location for the new project. Click Create. We’ll use this project to work with top-level programs in the subsequent sections of this article. Top-level program example in C# 9.0 Let’s look at a before-and-after example of how top-level programs can eliminate boilerplate code. Before top-level statements in C# 9.0, this is the minimal code you’d write for a console application: using System; namespace IDG_Top_Level_Programs_Demo { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); } } } When working with C# 9.0, we can avoid the noise and take advantage of top-level programs to write our code in a much simpler way. The following code snippet illustrates how you can take advantage of top-level statements to refactor the above code: using System; Console.WriteLine("Hello World!"); In either case, when the program is executed, you’ll see the string “Hello World!” displayed at the console window. Use methods in top-level programs in C# 9.0 You can use methods with top-level programs. Below is a code example that illustrates how you can use methods with top-level programs. System.Console.WriteLine(DisplayMessage("Joydip!")); System.Console.Read(); static string DisplayMessage(string name) { return "Hello, " + name; } When you execute the above program, you should see the output “Hello, Joydip!” appear in the console window: Use classes in top-level programs in C# 9.0 You can also use classes, structs, and enums in top-level programs. The following code snippet illustrates how you can use classes in top-level programs. System.Console.WriteLine(new Author().DisplayMessage("Joydip!")); System.Console.Read(); public class Author { public string DisplayMessage(string name) { return "Hello, " + name; } } When you execute the above program, the output will be similar to Figure 1. How top-level programs work in C# 9.0 So, how do top-level programs work exactly? What happens behind the scenes? Top-level programs are essentially a compiler feature. If you don’t write the boilerplate code, the compiler will generate it for you. Refer to the following piece code we wrote earlier. using System; Console.WriteLine("Hello World!"); The code displayed below (generated using the SharpLab online tool) shows what the compiler-generated code would look like. using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [CompilerGenerated] internal static class <Program>$ { private static void <Main>$(string[] args) { Console.WriteLine("Hello World!"); } } If you look at the compiler-generated code, you’ll see the [CompilerGenerated] attribute on top of the static class generated by the compiler. Top-level programs are a great new feature in C# 9.0, whereby the compiler automatically generates the boilerplate code for you behind the scenes. Top-level programs are great for simple programs that don’t have too many files and dependencies. Note that only one file in your application may use top-level statements; otherwise the compiler throws an error. One downside to top-level programs is that, if you’re new to C#, you might not be able to understand what’s happening in the code behind the scenes. A better way for beginners to learn C# will be using the Main method, and avoiding top-level statements until you understand how the Main method works. But those who have mastered Main will find top-level statements a very useful shortcut. How to do more in C#: How to use pattern matching in C# How to work with read-only collections in C# How to work with static anonymous functions in C# 9 How to work with record types in C# How to use implicit and explicit operators in C# Singleton vs. static classes in C# How to log data to the Windows Event Log in C# How to use ArrayPool and MemoryPool in C# How to use the Buffer class in C# How to use HashSet in C# How to use named and optional parameters in C# How to benchmark C# code using BenchmarkDotNet How to use fluent interfaces and method chaining in C# How to unit test static methods in C# How to refactor God objects in C# Related content feature 14 great preprocessors for developers who love to code Sometimes it seems like the rules of programming are designed to make coding a chore. Here are 14 ways preprocessors can help make software development fun again. By Peter Wayner Nov 18, 2024 10 mins Development Tools Software Development feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news Spin 3.0 supports polyglot development using Wasm components Fermyon’s open source framework for building server-side WebAssembly apps allows developers to compose apps from components created with different languages. By Paul Krill Nov 18, 2024 2 mins Microservices Serverless Computing Development Libraries and Frameworks news Go language evolving for future hardware, AI workloads The Go team is working to adapt Go to large multicore systems, the latest hardware instructions, and the needs of developers of large-scale AI systems. By Paul Krill Nov 15, 2024 3 mins Google Go Generative AI Programming Languages Resources Videos