This workspace contains file-based .NET apps. These are standalone .cs files that can be run directly without creating a project file or traditional project structure.
- No project file required - Run C# code directly from a
.csfile - Built-in CLI integration - Uses the standard
dotnetCLI, no additional tools needed - Scales to full projects - Can be converted to traditional project-based apps when needed
- Same C# language - Full C# language support, same compiler and runtime
- Cross-platform scripting - Supports shebang lines for Unix-like systems
dotnet run app.cs
# Or explicitly use --file option to avoid fallback behavior
dotnet run --file app.cs
# Or use the shortcut (if app.cs exists)
dotnet app.csAdd this line at the top of your .cs file:
#!/usr/bin/env dotnetThen make it executable and run directly:
chmod +x app.cs
./app.csFile-based apps support several directives that configure the build without needing a project file:
Use the #:package directive at the top of your file:
#:package Humanizer@2.14.1
#:package Microsoft.AspNetCore.OpenApi@10.*-*
using Humanizer;
// Your code here...Alternative CLI method:
dotnet package add <PackageId> --file yourfile.cs
dotnet package remove <PackageId> --file yourfile.csBy default, file-based apps use Microsoft.NET.Sdk. For web applications, use:
#:sdk Microsoft.NET.Sdk.WebConfigure build properties using #:property:
#:property LangVersion=preview
#:property TargetFramework=net10.0Reference other projects using #:project:
#:project ../MyLibrary/MyLibrary.csprojFile-based apps can be built like regular projects:
dotnet build app.csNote: Multi-file support is postponed for .NET 11. In .NET 10, only the single file passed as the command-line argument is part of the compilation.
File-based apps support several dotnet commands:
dotnet build app.cs # Build the program
dotnet publish app.cs # Publish (Native AOT by default)
dotnet pack app.cs # Create NuGet package
dotnet clean app.cs # Clean build artifacts
dotnet restore app.cs # Restore dependenciesNote: File-based apps have PublishAot=true set by default. To opt out, use #:property PublishAot=false directive.
DO NOT perform this action without explicit consent to convert to a project-based program.
When your file-based program grows in complexity, convert it to a traditional project:
dotnet project convert app.csThis command:
- Creates a new directory named after your file
- Generates a
.csprojfile with all directives translated to MSBuild properties - Moves your code to
Program.cs - Preserves all package references and settings
#!/usr/bin/dotnet run
#:sdk Microsoft.NET.Sdk.Web
#:package Microsoft.AspNetCore.OpenApi@10.*-*
var builder = WebApplication.CreateBuilder();
builder.Services.AddOpenApi();
var app = builder.Build();
app.MapGet("/", () => "Hello, world!");
app.Run();Build outputs are placed in a temporary directory unique to each user and hashed by file path. This:
- Keeps source directories clean
- Avoids conflicts between multiple users
- Enables artifact reuse for better performance
Artifacts are automatically cleaned every 2 days (removes artifacts unused for 30+ days). Manual cleanup:
dotnet clean-file-based-app-artifacts- Start simple - Use file-based apps for prototyping, learning, and small scripts
- Use directives - Leverage
#:package,#:sdk, and#:propertydirectives for configuration - Convert when needed - Use
dotnet project convertwhen your program outgrows a single file - Cross-platform scripts - Use shebang lines for executable C# scripts on Unix-like systems
- Version pinning - Specify exact package versions for reproducible builds
- Performance - Use
--no-cacheto force full rebuild if needed
- Requires .NET 10 Preview 4+ - This feature is not available in earlier versions
- File extension required - The file must have a
.csextension or start with#! - VS Code support - Install C# Dev Kit and switch to pre-release version (2.79.8+) for full support
- Directive order - Place all
#:directives at the top of the file before any code - Fallback behavior - If a project file exists in the current directory,
dotnet run file.cswill passfile.csas an argument to the project instead. Use--fileoption to avoid this - Entry point required - The file must contain top-level statements to be executable