-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Is your feature request related to a problem? Please describe.
When using single-file C# programs with dotnet run
, it's often necessary to use preprocessor directives like #:package
or #:property
. However, the values for these directives are static. This makes it difficult to test or run the same script against different configurations without manually modifying the source file. For example, in a CI/CD pipeline, I might want to test against different versions of a package, or toggle compiler settings like WarningsAsErrors
. Currently, this requires multiple source files, separate commits, or a script to modify the source file before execution, which is not ideal.
Describe the solution you'd like
I propose that the preprocessor directives for single-file C# programs support environment variable expansion. This would allow for dynamic configuration of directives at runtime, without needing to change the source code.
For example, the #:package
directive could support a syntax like this:
#:package mypackage@%MYPACKAGE_VERSION_TO_TEST%
If an environment variable MYPACKAGE_VERSION_TO_TEST
is set to 1.0.0
, dotnet run
would interpret the directive as if it were #:package mypackage@1.0.0
.
Similarly, for other directives like #:property
:
#:property WarningsAsErrors %WARN_AS_ERROR%
If an environment variable WARN_AS_ERROR
is set to nullable
, the directive would be interpreted as #:property WarningsAsErrors nullable
.
This would enable scenarios where the same script can be used with different configurations just by changing environment variables. This is particularly useful for:
- Testing against multiple versions of a dependency in CI/CD.
- Toggling build properties for different environments (e.g., Debug vs. Release).
- Quickly switching between different package sources or configurations for local development.
As an alternative, passing directive values via command-line arguments could also be considered, but environment variables are generally more convenient for CI systems and for keeping the command line cleaner.
The expected behavior for the variable expansion should be consistent with the System.Environment.ExpandEnvironmentVariables(String)
method. For example, if an environment variable is not found, the string should remain unchanged (e.g., %UNDEFINED_VARIABLE%
would stay as is). Source
Additional context
This feature would bring the flexibility of environment variables, common in many other scripting and development environments, to C# scripting with dotnet run
. It would make single-file C# scripts more powerful and adaptable for automation and testing.
Here are some concrete examples of the desired behavior:
Example 1: Dynamic Package Version
Given a file app.cs
with the following content:
#:package mypackage@%MYPACKAGE_VERSION_TO_TEST%
Console.WriteLine("Hello, World!");
And an environment variable set as:
MYPACKAGE_VERSION_TO_TEST=1.0.0
Running dotnet run app.cs
should be equivalent to running a file with:
#:package mypackage@1.0.0
Console.WriteLine("Hello, World!");
Example 2: Dynamic Property Value
Given a file app.cs
with the following content:
#:property WarningsAsErrors %WARN_AS_ERROR%
// csharp code that might have warnings
And an environment variable set as:
WARN_AS_ERROR=nullable
Running dotnet run app.cs
should be equivalent to running a file with:
#:property WarningsAsErrors nullable
// csharp code that might have warnings
The preprocessor should expand the environment variables before parsing the directives, following the same expansion rules as System.Environment.ExpandEnvironmentVariables
.