Top-Level Statements in C#

Vaibhav • September 11, 2025

In earlier chapters, we’ve written many C# programs using the traditional structure - a class named Program, a Main method, and curly braces everywhere. That structure is powerful, but it can feel overwhelming for beginners. Starting with C# 9.0, the language introduced top-level statements, a feature that simplifies your program’s entry point by removing unnecessary boilerplate.

In this article, we’ll explore what top-level statements are, how they work, when to use them, and how they fit into the broader evolution of C# as a modern, beginner-friendly language. We’ll also look at how they interact with other features like methods, variables, and namespaces - all of which you’ve already learned in previous chapters.

What Are Top-Level Statements?

Top-level statements allow you to write C# code directly - without wrapping it in a class or a Main method. This is especially useful for small programs, demos, scripts, and learning exercises.

// Traditional C# program
using System;

class Program
{
    static void Main()
    {
        Console.WriteLine("Hello, world!");
    }
}

With top-level statements, you can write the same program like this:

using System;

Console.WriteLine("Hello, world!");

That’s it. No class, no method, no extra braces. The compiler automatically wraps your code in a hidden Main method behind the scenes.

Top-level statements are only allowed in one file per project. That file becomes the program’s entry point.

Why Use Top-Level Statements?

Top-level statements make your code cleaner and easier to read - especially for small programs. They’re perfect for:

  • Learning and teaching C#
  • Writing quick prototypes
  • Building console utilities
  • Creating minimal APIs

They also reduce cognitive load for beginners. Instead of explaining classes and methods on day one, you can focus on core programming concepts like variables, loops, and conditionals.

How the Compiler Handles Top-Level Code

When you use top-level statements, the compiler automatically generates a class and a Main method for you. Your code becomes the body of that method. For example:

Console.WriteLine("Welcome!");
int x = 5;
Console.WriteLine(x * 2);

Internally, the compiler transforms this into something like:

internal class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Welcome!");
        int x = 5;
        Console.WriteLine(x * 2);
    }
}

You don’t see this transformation - but it’s important to understand that top-level statements are just syntactic sugar. They don’t change how your program runs.

Using Variables and Methods

You can declare variables and call methods just like you would inside a Main method. For example:

int a = 10;
int b = 20;

Console.WriteLine(Add(a, b));

int Add(int x, int y)
{
    return x + y;
}

This works because the compiler allows method declarations after top-level code. You can even use local functions - a concept introduced in Chapter 6 - to keep your logic organized.

Note: You must declare methods after the top-level statements that use them. Otherwise, the compiler won’t recognize them.

Working with Namespaces and Usings

You can still use namespaces and using directives with top-level statements. For example:

using System;

Console.WriteLine("Today's date is:");
Console.WriteLine(DateTime.Now);

This behaves exactly like it would in a traditional program. You can also define namespaces and classes - but they must come after the top-level code.

Returning Values from Top-Level Programs

If your program needs to return an exit code, you can use the return statement directly:

Console.WriteLine("Running checks...");

bool success = true;

if (!success)
    return 1; // Non-zero exit code

return 0; // Success

This is useful for command-line tools and scripts that need to signal success or failure to the operating system.

Limitations of Top-Level Statements

While top-level statements are great for small programs, they have some limitations:

  • You can’t use them in multiple files - only one file per project can contain top-level code.
  • You can’t define multiple entry points - the compiler picks the file with top-level statements as the main one.
  • You must declare methods and types after the top-level code - not before.
  • You can’t use async directly - unless you return a Task.

These limitations are minor for most use cases, but it’s good to be aware of them - especially as your projects grow.

Top-Level Statements in Real Projects

Top-level statements aren’t just for learning - they’re used in real-world projects too. For example, .NET 6 introduced minimal APIs, which use top-level statements to define web endpoints:

var app = WebApplication.Create();

app.MapGet("/", () => "Hello, world!");

app.Run();

This is a complete web application - written using top-level statements. It’s fast, clean, and easy to understand.

Top-level statements are used in many .NET templates - including console apps, web APIs, and Blazor projects.

Mixing Top-Level and Traditional Code

You can mix top-level statements with traditional code - but you must follow the rules. For example:

Console.WriteLine("Starting...");

class Helper
{
    public static void SayHello()
    {
        Console.WriteLine("Hello from Helper!");
    }
}

This works because the class is declared after the top-level code. You can then use it in later statements or methods.

Common Mistakes and How to Avoid Them

Here are a few common mistakes developers make with top-level statements:

  • Trying to declare methods before top-level code - which causes compiler errors.
  • Using top-level statements in multiple files - which confuses the compiler.
  • Mixing return and void logic - which leads to inconsistent behavior.
  • Assuming top-level code is faster - it’s not; it’s just cleaner.

These mistakes are easy to avoid once you understand how the compiler handles top-level code.

Design Tips for Using Top-Level Statements

Top-level statements are a design choice. Use them when they make your code clearer:

  • Use them for small programs, demos, and scripts.
  • Avoid them in large projects with multiple entry points.
  • Use them with minimal APIs and console tools.
  • Keep your top-level code short and focused.

These tips help you write clean, maintainable code - whether you’re building a quick utility or a full application.

Summary

Top-level statements simplify your C# programs by removing boilerplate and letting you write code directly. They’re perfect for learning, prototyping, and building small tools. You’ve learned how to use top-level statements, how the compiler handles them, how to declare variables and methods, and how to mix them with traditional code.

By using top-level statements, you make your code cleaner, more approachable, and easier to maintain. In the next article, we’ll explore Target-Typed new - a feature that makes object creation more concise and expressive.