Categories
.NET .NET 10 ASP.NET Core Aspire Automation Azure Blazor C# CLI Code Desktop Developer Getting Started Linux macOS Mobile Visual Studio VS Code Web What's New Windows

Using C# Ignored Directives: A Guide for Programmers

Execute a C# source file directly from the CLI without necessitating a project file – dotnet run app.cs

C# – Preprocessor Directives are highly useful for writing code that can be compiled conditionally, depending on factors like the target framework, target platform, or build configuration.

For example:

#if NET9_0_OR_GREATER
// The code within this block will execute only on .NET 9 or higher
#endif

#if ANDROID
// The code within this block will execute only on the Android OS
#endif

#if DEBUG
// The code within this block will execute only in Debug mode
#endif

C# – Ignored Directives have a similar syntax but are ignored by the compiler because they are for tooling.

The real purpose of this feature is to execute a C# source file directly from the CLI. It doesn’t need a project file. Now, even the plain console app requires a project file, despite the much-simplified top-level statements feature.

For now, there are five directives implemented in .NET 10:

// shebang (or) hashbang - Supported only on Linux
#!/usr/bin/dotnet run

// To use a different SDK other than the default one
#:sdk Microsoft.NET.Sdk.Razor

// To define a project property
#:property TargetFramework=net10.0

// To reference a NuGet package
#:package Microsoft.Extensions.Hosting@10.*-*

// To reference a project
#:project MyApp.UI\MyApp.UI.csproj

Usage:

  • Each directive should be on a separate line.
  • All definitions must precede any valid C# compilation token, including #define
  • Define the sdk directive once; property, package, and project can be defined multiple times.
    • A valid SDK identifier must follow the sdk directive and have a whitespace between them.
      • For example, running Aspire as a file-based app
      • #:sdk Aspire.AppHost.Sdk@9.5.0
    • For both property and package, a valid identifier and its value must follow the directive with whitespace separating them.
    • Define property details as name=value
      • #:property LangVersion=preview
    • Define package details as Id@Version
      • #:package Microsoft.Extensions.Hosting@10.*-*
      • The package value supports dynamic versioning.
    • Project directive should point to the path of the referenced project file.
      • #:project MyApp.UI\MyApp.UI.csproj
  • shebang must be the first line before the byte order mark (BOM) for the shell to recognize it.
  • Any other invalid directive will be reported as an error.

Sample Code:

Console:

Utilizes the default SDK and its properties, employing the top-level statements feature.

Console.WriteLine("Hello, C#!!!");

Save this as a C# file, say Console.cs, and execute the below command:

dotnet run Console.cs

WinForms:

The properties are quite different, even while targeting the default SDK.

Note: The PublishAot property will be true by default for the File-based Apps feature. Turn it off when using WinForms.

#:property TargetFramework=net10.0-windows
#:property UseWindowsForms=true
#:property OutputType=WinExe
#:property PublishAot=false

Application.Run(new Form() { Text = "Hello C#" });

Save this as a C# file, say Forms.cs, and execute the below command:

dotnet run Forms.cs

Web – ASP.NET Core:

Utilizes the Web SDK with the Minimal API feature.

#:sdk Microsoft.NET.Sdk.Web

var builder = WebApplication.CreateBuilder(args);
// Configure builder
var app = builder.Build();

app.MapGet("/", () => "Hello ASP.NET Core!!!");

app.Run();

Save this as a C# file, say Api.cs, and execute the below command:

dotnet run Api.cs

And then navigate to the link http://localhost:5000 in a web browser.

Hashbang (or) Shebang:

This feature works only on Linux, and the directive must be on the first line of the source file.

Typically, each file in the Linux file system has three permissions: Read (r), Write (w), and Execute (x).

If the file has execute permission and a hashbang defined, it can be run directly from the CLI. It functions like an executable.

#!/usr/bin/dotnet run

Console.WriteLine("Hello, C#!!!");
./Console.cs

To grant execute permission, run the command below.

chmod +x Console.cs

Converting it to a Project:

Tooling support is provided for moving the source to a project using the command below.

dotnet project convert Forms.cs

This process will create a project file and transfer all Ignored Directives into the respective project properties and package references.

Limitations:

  • The dotnet run command now accepts only one file as its parameter.
    • It can take multiple files, but they are ignored.
    • Support for multiple files in .NET 11

Next Steps:

  • To try this new feature, download and install the latest .NET 10 SDK from the SDK Downloads page.
  • .NET 10 Preview works with VS2022 (17.13+), VS2026 Insiders, and VS Code using the C# Dev Kit extension.

GitHub Discussion:

This feature is actively discussed here on GitHub.

Happy coding. Stay connected as we continue to learn and share the experiences from this exciting journey of being a .NET developer.

One reply on “Using C# Ignored Directives: A Guide for Programmers”

Comments are closed.

Discover more from Developer Thoughts

Subscribe now to keep reading and get access to the full archive.

Continue reading