はじめに
.NET10 Preview4からfile-based apps
という.csproj
なしで.cs
を実行できる機能が追加されました。
手軽に利用できるようになったのは勿論のこと、特にCI/CDで.cs
を利用する手法がより広がっていくのではと思っています。前にProcessX(Zx) + ConsoleAppFramework
の組み合わせならCI/CDでbash/zsh/pwshの代わりに使っても良いのではと書いたことがあるのですが、より現実味を帯びてきたと思います。
あとActionsのカスタムシェルを使ってshell: dotnet run {0}
とかできたらいいなと思うのですが、調べた感じランナーにインストールされている.NETのバージョンのこともありますし少なくとも現段階では無理そうな気がしています。(追記にコメントしました)
GitHub Actions のワークフロー構文 - GitHub Docs
背景を説明すると、一応.csx
とかもあったのですが、基本的に.NETでは.csproj
がないと実行をすることができませんでした。
$ tree . └── ConsoleApp ├── ConsoleApp.csproj └── Program.cs
しかし今回のfile-based apps
と呼ばれる機能を用いれば、.csproj
がいらなくなります。つまり、Program.cs
のような単一ファイルだけで実行までできるというわけです。
$ chmod +x ./Program.cs $ ./Program.cs
導入〜使い方までを一通り紹介したいと思います。
導入方法
VSCodeで開発環境を整える
Riderだとどうなのか確認できていないのですが、VS Codeであれば既にfile-based apps
に対応しています。VS CodeにC# Dev Kit
という拡張機能があるのでpre-release
(私はv1.20.33
)をインストールします。
またC#
という拡張機能でも、pre-release
のv 2.79.8
以上にしてください。

基本的な使い方
まずは実際に利用する方法を紹介します。
任意の場所に以下の内容の.cs
を作成してください。
#!/usr/bin/env dotnet run Console.WriteLine("Hello World!");
Shebang
があるので、実行権限を与えて実行すればOKです。
$ chmod +x ./sample.cs $ ./sample.cs Hello World!
使い方
NuGet Packageを参照する
#:package
の後ろに、NuGet
のパッケージ名とバージョンを記述します。
#!/usr/bin/env dotnet run #:package MessagePack@3.1.3 using MessagePack;
パッケージ名が分からない方は、nuget.org
を確認すると良いでしょう。
www.nuget.org
デフォルトのSDKと変更方法
デフォルトのSDKはMicrosoft.NET.Sdk
です。WebAPIを作成したいなどでMicrosoft.NET.Sdk.Web
といった別のSDKを利用したい場合は#:sdk
を記述します。
learn.microsoft.com
#!/usr/bin/env dotnet run #:sdk Microsoft.NET.Sdk.Web var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run("http://localhost:8080");
MSBuildのpropertyを設定する
MSBuildのProperty
を記述するためには、#:property
を用います。
<!-- csprojでの記述例 --> <PropertyGroup> <LangVersion>preview</LangVersion> </PropertyGroup>
#!/usr/bin/env dotnet run #:property LangVersion preview
Shebang
先ほどからしれっとずっと使っていましたが、ちゃんとShebang
も用意してくれています。
#!/usr/bin/env dotnet run
$ chmod +x ./sample.cs $ ./sample.cs
file-based appをやめる
複雑になってきたら、.csproj
を活用した通常のproject-based apps
に変換することも可能です。コマンドはdotnet project convert .csへのパス
です。
$ tree . └── sample.cs # migrate $ dotnet project convert sample.cs # .csprojが作成されていることが確認できる $ tree . └── sample ├── sample.cs └── sample.csproj
ProcessX + ConsoleAppFrameworkの組み合わせ
ConsoleAppFramework v5
とProcessX(Zx)
を組み合わせたオススメ構成を紹介して終わりたいと思います。
GitHub - Cysharp/ProcessX: Simplify call an external process with the async streams in C# 8.0.
GitHub - Cysharp/ConsoleAppFramework: Zero Dependency, Zero Overhead, Zero Reflection, Zero Allocation, AOT Safe CLI Framework powered by C# Source Generator.
#!/usr/bin/env dotnet run #:package ProcessX@1.5.6 #:package ConsoleAppFramework@5.4.1 using ConsoleAppFramework; using Zx; using static Zx.Env; verbose = false; var app = ConsoleApp.Create(); // root command app.Add("", async () => { var tools = await "dotnet tool list -g"; log(string.Join(",", tools)); }); // 例: ./sample.cs echo --msg "Hello, World!" app.Add("echo", (string msg) => log(msg)); // 例: ./sample.cs sum 5 10 app.Add("sum", ([Argument] int x, [Argument] int y) => log(x + y)); app.Run(args);
$ ./sample.cs Package Id Version Commands ------------------------------------------------------------------------- coverlet.console 6.0.4 coverlet $ ./sample.cs sum 1 2 3 $ ./sample.cs echo --msg "hello, world!!!" hello, world!!!
追記
色々調べてみて、GitHub Actionsでshell: dotnet run {0}
を利用できるようにするPRをrunnerに出してみてます!
github.com