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
sdkdirective once;property,package, andprojectcan be defined multiple times.- A valid SDK identifier must follow the
sdkdirective 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
- A valid SDK identifier must follow the
shebangmust 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 runcommand 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”
[…] Using C# Ignored Directives: A Guide for Programmers (Vijay Anand E G) […]