error CS8803: Top-level statements must precede namespace and type declarations.
In a Program.cs without a Main method, the loose statements have
to come first and any class, record, enum or namespace after them. Move your class below
the last statement and the build passes.
Nothing else needs to change: the class keeps working from the statements above it, because C# does not care where in the file a type is declared, only that the statements lead.
The error
...\Program.cs(6,1): error CS8803: Top-level statements must precede namespace and type declarations. [...\FixLab.csproj]
Build FAILED.
The project folder was shortened to ...; the rest is as printed.
Why it happens
Since .NET 6 the console template has no class Program and no
Main; it is one line, Console.WriteLine("Hello, World!");. Many
people coming from older tutorials, or from languages where you define things before you
use them, write their class first:
class Greeter
{
public static string Hello(string name) => $"Hello, {name}!";
}
Console.WriteLine(Greeter.Hello("Maria Garcia"));
Top-level statements are a shortcut: the compiler collects them into a generated entry
point method. To keep that unambiguous, the language requires all of them to sit at the
top of the file, before any type or namespace declaration. The first statement found
after a declaration is the one reported, here line 6, column 1, the
Console.WriteLine. The class itself is fine; its position is the problem.
The fix
Console.WriteLine(Greeter.Hello("Maria Garcia"));
class Greeter
{
public static string Hello(string name) => $"Hello, {name}!";
}
With the statement first, the project built with warnings treated as errors and printed
Hello, Maria Garcia!. Once a program grows past a couple of classes, the
tidier fix is to give each class its own file, Greeter.cs next to
Program.cs; types in other files of the project are visible from the
top-level statements without any extra step.
If you prefer the classic layout, you can also delete the top-level statements and write
class Program with a static void Main() yourself, or start the
project with dotnet new console --use-program-main, which generates that
layout inside a file-scoped namespace FixLab;.
How it was reproduced
A dotnet new console project on .NET SDK 10.0.403 (net10.0, nullable and
implicit usings on, no packages), with Program.cs replaced by the class-first
code above. dotnet build reported one CS8803 error; with the class moved below
the statement, dotnet build --no-incremental -p:TreatWarningsAsErrors=true
succeeded and dotnet run printed the greeting.
Frequently asked
- Where do I put a class when using top-level statements?
- After the last top-level statement in Program.cs, or better in its own .cs file in the same project. Types in other files are visible to the top-level statements automatically.
- Can I use a namespace in Program.cs with top-level statements?
- Yes, as a block below the statements: namespace FixLab { class Greeter { ... } } after the statements built and ran. A file-scoped namespace FixLab; there gives error CS8956, File-scoped namespace must precede all other members in a file. Namespaced types are tidier in their own .cs file.
- How do I go back to a Main method in .NET 6 and later?
- Replace the top-level statements with a class Program containing static void Main(string[] args), or create the project with dotnet new console --use-program-main, which generates that layout.
More decoded compiler errors are in the Fixes category.