NDepend Blog

Improve your .NET code quality with NDepend

.NET 10.0 dotnet run app.cs or file-based program

August 13, 2025 5 minutes read

dotner run app.cs

This post covers a new .NET 10 feature that lets you build and run a single C# file without creating a .csproj project file. We will demo it, outline its capabilities, note its limitations and suggest possible workarounds.

dotnet run app.cs

Let’s create a simple C# source file named app.cs. Its code relies on top level statement. This means that there is no Main() method nor Program class explicitly defined.

Now let’s open a command window in the directory containing the file app.cs. Just type:

Et voilà! It takes 13 seconds to restore and compile and finally Hello, world gets printed.

dotnet run app.cs first execution

We can see that a temporary directory gets created. It actually contains the app.dll executable file.

If we modify app.cs and re-run dotnet run app.cs the same temporary directory gets re-used. This time it is much faster since no more restoring is required:

Now, let’s explore the available features, which use new preprocessor directives—lines that begin with #:.

#:sdk to add SDK reference

With #:sdk we can import a .NET SDK. As a consequence it’s now possible to run a complete ASP.NET Minimal API from just one .cs file. Here’s an example:

Just run dotnet run app.cs then open http://localhost:5000 in your browser et voilà!

#:package to add Nuget package reference

One or several Nuget package reference can be added this way:

Wildcards can be used in version numbers, and the examples below also work. The wildcard resolves to the latest package version.

#:property to add project property

The program below rely on the C# 14 extension everything feature. As long as .NET 10.0 is in preview it requires both #:property directives:

The two #:property directives are equivalent in .csproj of:

#:project to reference a .csproj project file

It is possible to reference a project file through its relative or absolute file path:

Notice that MyClassLibrary.dll and .pdb get copied to the temporary path. Also, Newtonsoft.Json.dll remains from a previous execution.

dotnet run app.cs first dll copied

#!/usr/bin/dotnet run (Unix-like only)

A script line beginning with #! is known as a shebang. On Unix-like systems, it tells the OS how to execute the file directly. Here, it specifies /usr/bin/dotnet run <file> as the command. Once you make the script executable with chmod +x app.cs, you can run it straight from the shell:

dotnet publish app.cs

It is possible to publish your file based application with this simple command: dotnet publish app.cs. The application gets published in the temporary folder C:\Users\pat\AppData\Local\Temp\dotnet\runfile\app-b5e84c88afcfdf33c1655e121991c2cd65d9f0aa4c95adfe302344c3d2bb61ac\publish\release:

dotnet publish app.cs

Missing project file workaround with Directory.Build.props

You can work around some of the current directive limitations by using a Directory.Build.props file. For example we can rewrite the extension members sample by removing the #:property directives.  The file app.cs content is:

Then create a file named Directory.Build.props in the same directory (or a parent directory) with this content:

dotnet run app.cs now works because it takes account of Directory.Build.props. In fact under the hood a virtual project is built in memory through the Microsoft.DotNet.Cli.Commands.Run.VirtualProjectBuildingCommand.

When to use dotnet run app.cs?

  • Beginner-friendly – The .NET team aims to simplify learning for newcomers. Like Node.js or Python, .NET now supports a smooth single-file experience.
  • Prototyping – File-based program is ideal for quick and dirty prototypes.
  • Scripts – Tasks that once required Bash or PowerShell can now be written just as easily in C#.
  • Samples – Instead of creating a separate folder and project for each example, you can keep multiple sample apps in one folder, with each .cs file acting as its own runnable example. In this scenario having a common Directory.Build.props file to factorize some properties makes even more sense.

Here’s a Reddit comment about this post that speaks for itself: (from )

“I was lukewarm on this until I found the perfect use case for it last night.

I was working on a project that doesn’t use .NET at all, and I just needed to convert some binary data from one format into another format. I wrote a 20-line convert.cs in about 5 minutes, and just ran it straight from the command line.

I didn’t have to set up a project, and it didn’t spit out a bin folder with a bunch of junk in it that I would have to add to .gitignore. The script can just live in the source tree for this project without adding any additional infrastructure. And I can write like 5 more of these that I’ll need for other formats.”

dotnet project convert app.cs

Eventually, you may want to convert your single-file program into a full project that requires a .csproj file.

Running the command dotnet project convert app.cs sets up a project file automatically: it makes a folder for your file, adds a .csproj, remove #:directives in app.cs, and turns these directives into proper MSBuild settings and references.

dotnet project convert app

Conclusion

File-based program is not the first technology that let’s .NET developers run C# code without a project file. For years, the projects CS-Scriptdotnet-scriptCake or even LinqPad have enabled scripting, REPLs (Read-Eval-Print Loop), and other lightweight ways to run C# without a full project. Thanks to the new dotnet run app.cs built-in support, developers can start coding right away—no extra setup, installation, or configuration needed.

.NET 10 will supports single file-based program but multiple files-based program is on its way for .NET 11. “We’re moving support for multi-file out to .NET 11 so we can focus on making the single-file experience great in .NET 10.”

As of August 2025, this feature is still in preview. This post will be updated as it progresses toward general availability with .NET 10 in November 2025.

 

Leave a Reply

Your email address will not be published. Required fields are marked *