Important Note: The ability to run C# files directly using
dotnet run file.cs
as described here is a feature currently available in the .NET 10 Preview SDK. Ensure you have the .NET 10 Preview SDK installed to follow this tutorial. This feature provides a streamlined way to execute simple C# programs without the traditional.csproj
project file setup.
Welcome! This tutorial is designed to guide you through the experience of running a simple C# application directly from a source file using the .NET 10 Preview SDK. This approach, often referred to as running "file-based programs", can be particularly useful for quick tests, learning exercises, or simple scripts where the overhead of a full project structure feels unnecessary. Our goal today is not just to execute some code, but to understand how the .NET Command Line Interface (CLI) in .NET 10 Preview enables this workflow, including how to incorporate external libraries (NuGet packages) and control the underlying SDK used.
Throughout this session, think of me as your guide. We'll take small, manageable steps together. You'll write a basic C# program, and then we'll use the dotnet run
command to compile and run it directly. You'll see the output immediately, connecting your action with its result. This immediate feedback is crucial for learning. Don't worry about memorizing every detail right now; the focus is on the doing and observing the outcome. By the end, you'll have successfully run C# code without the usual project setup and gained familiarity with this powerful new feature of the .NET 10 Preview SDK.
Setting the Stage: Your First C# File
Let's begin by creating our C# source file. Open your favorite text editor or integrated development environment (IDE). Create a new file and name it app.cs
. The .cs
extension is important.
Inside app.cs
, let's write a very basic C# program using top-level statements:
// app.cs
using System;
Console.WriteLine("Hello from a project-less world in .NET 10 Preview!");
This code simply prints a message to the console. Save this file.
Running the Basic Code
Now, let's run the simple code we just wrote. Open your terminal or command prompt, navigate to the directory where you saved app.cs
, and execute the following command:
dotnet run app.cs
Assuming you have the .NET 10 Preview SDK correctly installed and configured in your PATH, the .NET CLI will compile your app.cs
file in memory and run it. You should see the output:
Hello from a project-less world in .NET 10 Preview!
This demonstrates the basic capability. The CLI implicitly creates a minimal project definition based on the default dotnet new console
template for the installed SDK version to compile and run your single file.
Adding NuGet Packages with Directives
A key enhancement in the .NET 10 Preview for file-based programs is the ability to reference NuGet packages directly within the source file using special comments called app directives. Let's modify our app.cs
to use the popular Humanizer
package.
First, add the directive at the top of your app.cs
file:
#:package Humanizer@2.*
Now, modify the code to use the package:
// app.cs
#:package Humanizer@2.*
using Humanizer;
// Example: Pluralize a word
string singular = "hobby";
string plural = singular.Pluralize();
Console.WriteLine("Plural of '{0}' is '{1}'", singular, plural);
Save the changes. Now, run the file again using the same command:
dotnet run app.cs
This time, the .NET CLI will detect the #:package
directive. It will resolve and download the Humanizer
package (if not already cached) and include it during the implicit compilation. The output should now pluralize the word "hobby":
Plural of 'hobby' is 'hobbies'
This demonstrates how easily you can incorporate external libraries into your single-file programs using directives, making this feature much more powerful for scripting and small utilities.
Specifying SDK and Properties (Advanced)
The #:sdk
directive allows specifying the project SDK (e.g., #:sdk Microsoft.NET.Sdk.Web
for a web context, though single-file execution primarily targets console apps). The #:property
directive allows setting MSBuild properties (e.g., #:property LangVersion=preview
).
// Example showing potential directives (syntax based on proposal)
#:sdk Microsoft.NET.Sdk
#:property LangVersion=preview
#:package System.CommandLine
// ... rest of your code
These directives further configure the implicit project file generated behind the scenes. While the default (Microsoft.NET.Sdk
for console) often suffices, these provide finer control when needed.
Direct Execution with Shebang (Unix-like Systems)
On Unix-like operating systems (Linux, macOS), you can make your C# file directly executable like a shell script by adding a shebang line at the very beginning of the file and setting the execute permission.
Modify your app.cs
file to include the shebang line pointing to dotnet run
:
#!/usr/bin/env dotnet run
#:package Humanizer@2.*
using Humanizer;
// Example: Pluralize a word
string singular = "hobby";
string plural = singular.Pluralize();
Console.WriteLine("Plural of '{0}' is '{1}'", singular, plural);
Important: The shebang line (#!/usr/bin/env dotnet run
) must be the very first line in the file.
Next, you need to make the file executable. Open your terminal in the directory containing app.cs
and run:
chmod +x app.cs
Now, you can execute the C# file directly:
./app.cs
The operating system will use the shebang line to invoke /usr/bin/env dotnet run
, which in turn will execute your C# code, including processing any directives like #:package
. You should see the same output as before, but without explicitly typing dotnet run
.
This makes C# files feel even more like native scripts on these platforms, further lowering the barrier for simple tasks and automation.
Understanding the Context and Limitations
Remember, this file-based execution model in .NET 10 Preview is designed for simplicity and quick tasks. The implicit project created is minimal. If your application involves multiple source files interacting in complex ways, requires intricate build configurations, targets multiple frameworks, or has extensive dependencies, transitioning to a standard project structure using a .csproj
file is the recommended approach. This feature provides a fantastic low-friction entry point, not a replacement for the full project system in complex scenarios.
The Grow-Up Path
Should your single-file program evolve and require the structure of a full project, .NET 10 Preview provides a command to facilitate this transition. Running dotnet project convert app.cs
(syntax based on the proposal) would materialize the implicit project file (.csproj
) on disk, allowing you to manage it explicitly.
This concludes our revised tutorial on running C# without a project file using the .NET 10 Preview SDK. You've seen how to run basic files and incorporate NuGet packages using directives, providing a powerful yet simple way to execute C# code.
Top comments (2)
Thanks for this article. But why didn't you explain how it works internally? I mean, is it compilation as before or is it already interpretation?
@barysevichdaminik Good question! This feature was just released recently. I can't find any documents mentioning it. Based on my observation, the file is compiled and its compilation output (bin, obj) is located in
~/.local/share/dotnet/runfile/<FileName>-<Hash|ProjectId>/
for my case.