.NET 10 の File-based Apps を試してみた
はじめに
本稿執筆の2日前(2025-05-28)に Microsoft Dev Blogs に Announcing dotnet run app.cs – A simpler way to start with C# and .NET 10 という記事が投稿されました。
ものすごく雑にいうと 「.NET 10 からは File-based Apps という C# のコード単体を動かす機能が搭載されるよ!」 という感じの内容が書かれており、個人的には「待ってました!!」という感じだったので早速試してみました。
更新履歴
- 2025-05-31 いぬいぬさんよりコメントにてご指摘いただいた点を修正
TL; DR
#!/usr/bin/env dotnet run
Console.WriteLine("Hello World !!");
chmod +x app.cs
./app.cs
Hello World !!
便利!
kwsk
事前準備
.NET 10 SDK をインストール
.NET 10 は本稿を執筆している 2025-05-30 時点では Preview 版なので、通常の .NET SDK ダウンロードページからはダウンロードできません。
こちらのページから、環境に応じたバイナリをダウンロードし、インストールしてください。
global.json
を配置 (Optional)
.NET SDK を複数バージョンインストールしている環境の場合、dotnet
コマンド実行時に利用される .NET SDK を .NET 10 にする必要があります。
そのため、利用する .NET のバージョンを指定するための設定ファイルを作業ディレクトリに配置します。
{
"sdk": {
"version": "10.0.100-preview.4.25258.110"
}
}
C# コード
#!/usr/bin/env dotnet run
Console.WriteLine("Hello World !!");
これだけ!
shebang として /usr/bin/env dotnet run
を用いているのがポイントです。
こうすることで、実質的に dotnet run app.cs
と指定したような状態になるため、.NET 10 の File-based Apps として実行されることになります。
なお、/usr/bin/env dotnet
を用いているのは、環境毎に dotnet
コマンドのインストール先が異なっている可能性があるため、env
コマンドを用いて PATH が通っている dotnet
コマンドを探しています。
また、.NET SDK による暗黙の Global Using 追加もちゃんと動くので、System
名前空間の省略もできています。
実行権限付与
実行ファイルとして起動するために、実行権限を与えておきます。
chmod +x app.cs
実行!
./app.cs
Hello World !!
🎉🎉🎉
One more thing…
単に C# の構文をそのまま実行 [1] できるだけだと「ふーん」って感じかもですが、そこは流石の Microsoft さん。
ちゃんと(とは?)NuGet Packages の利用もできるようになっています。
構文としては #:package {PackageName}@{Version}
で用いるパッケージを指定可能です。
例えば、YAML パーサライブラリである VYaml を使ってみます。
#!/usr/bin/env dotnet run
#:package VYaml@1.1.1
using System.Text;
using VYaml.Annotations;
using VYaml.Serialization;
var yaml = """
foo:
- aaa
- bbb
bar:
baz: 1
quz: true
""";
var sample = YamlSerializer.Deserialize<Sample>(Encoding.UTF8.GetBytes(yaml));
Console.WriteLine($"{sample.Foo[1]}, {sample.Bar.Baz}, {sample.Bar.Quz}");
[YamlObject]
public partial record Sample(
string[] Foo,
Bar Bar
);
[YamlObject]
public partial record Bar(
int Baz,
bool Quz
);
では、実行してみましょう。
chmod +x yaml.cs
./yaml.cs
bbb, 1, True
ちゃんと動いていますね!
ここで紹介した #:package
の他にも、Microsoft.NET.Sdk
以外の SDK を利用するための #:sdk
だったり、MSBuild のプロパティを書き換えるための #:property
だったり、色々と気の利いた機能が盛り込まれているようなので、詳しく知りたい方は公式ブログの記事をご参照ください。
まとめ
本稿では .NET 10 でサポートされるようになる File-based Apps を試してみました。
手元でサッと実装を試したり、動くコードスニペットを Gist とかで公開しやすくなるので嬉しいですね!
なお、今回の調査を行ったプロジェクトはこちらのリポジトリで公開しております。
サンプルとして、CI/CD 基盤を構築する上で欠かせない Unity の YAML ファイル(ProjectSettings.asset
)のパースを行っていますので、基盤整備に明け暮れている諸氏は参考にしてみても良いかもしれませんw
(GitHub Actions の jobs.steps.shell
に dotnet run
を渡せたりすると嬉しいけど、そこは未調査です。機会があれば調べてみます。)
この記事が「いいね!」と思った方は、♥ ボタンを押してもらえると筆者が喜びます😆
-
本稿の初版では「インタプリタ実行」という表現を用いていましたが、File-based Apps はインタプリタ実行しているわけではなく、コンパイル結果を Temp 領域に保存しつつ実行しているだけとのことです。いぬいぬさんご指摘ありがとうございます! ↩︎
Discussion
この方法はC#コードのインタプリタ実行ではなく、普通にコンパイルしたあとに実行されます。
「C#スクリプト」と一部で呼ばれていますが、スクリプトのように扱えるだけで、
実際のプログラムとしては以前からのC#のプログラムと同じです。
公式ブログにも、「重要:これはC#の別の方言や別のモードではありません」とあります。
bin/やobj/とかのビルド出力結果物は見えないTemp以下に出力されていて、
2回目以降の
dotnet run
の時にはこの結果がキャッシュとして使われるそうです。ご指摘ありがとうございます!
記事を修正いたしました。