はじめに
.NET は常に進化し、開発体験をよりシンプルかつ効率的にすることを目指しています。最近、.NET CLI(コマンドラインインターフェース)に、プロジェクトファイルを作成せずに C# ソースファイルを直接実行できる、待望の新機能が提案されました。この機能は ファイルベースプログラム (File-based Programs) と呼ばれ、.NET 10 で dotnet run file のサポートが導入され、dotnet sdk から直接実行できるようになります。現在 .NET 10 Preview 4 ですでに利用可能で、最新の .NET 10 SDK をダウンロードしてお試しいただけます。以前作成した dotnet-exec の一部の機能が、ネイティブの SDK サポートで利用できるようになりました。
概要
従来の .NET アプリケーション開発では、簡単なコードを実行するだけでも、プロジェクトファイル(.csproj)が必要でした。ファイルベースプログラムはこのハードルを取り払い、コマンドラインから任意の C# ファイルを直接実行できるようにします。
echo 'Console.WriteLine("Hello C#!");' > hello.cs
dotnet run hello.cs
プロジェクトファイルも複雑な設定も不要。まるでスクリプトのように C# を実行できます!

動作の仕組み
dotnet run file.csを実行すると、CLI は自動的にそのファイル用の「暗黙のプロジェクト」(仮想プロジェクトファイル)をメモリ上に生成します。これはdotnet new consoleテンプレートを使用して作成されたプロジェクトと同等の効果を持ちます。これにより、単一ファイルでスクリプトを実行する場合でも、標準的なプロジェクト開発と同じ動作が保証されます。実装方法は、最近の dotnet-exec の project compiler と非常に似ていますが、さらに優れています。実際のファイルを作成せずに、仮想プロジェクトファイルとして実装されています。- 対象ファイルと同じディレクトリおよびサブディレクトリ内のすべての
.csファイル(ユーティリティクラスやリソースなど)がコンパイルに含まれます。 - 関連するビルドファイル(例:
Directory.Build.props)も自動的に適用されます。 - 実行したファイルにエントリポイント(入口)メソッドがない場合は、誤操作を防ぐためにエラーメッセージが表示されます。例:

その他の使い方
ファイルプログラムの拡張をサポートするために、新しい
#:ディレクティブが追加されました。プロジェクトファイルのコンパイル時には自動的に無視され、ファイルプログラムでは解析されてプロジェクトファイル内の SDK、参照、プロジェクトプロパティ設定に変換されます。ファイルの先頭に特別なディレクティブ(例:
#:sdk Microsoft.NET.Sdk.Web、#:package、#:property)を記述することで、NuGet 依存パッケージやプロジェクトプロパティを宣言できます。例:
#:sdk Microsoft.NET.Sdk.Web #:package System.CommandLine@2.0.0-* #:property TargetFramework net10.0
`#:sdk Microsoft.NET.Sdk.Web` を指定することで、単一ファイルの WebApplication を作成できます。
```csharp
#:sdk Microsoft.NET.Sdk.Web
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
await app.RunAsync();
dotnet run webapi.cs を実行して単一ファイルの webapi を実行します。

API にアクセスします。

NuGet パッケージの参照やプロパティの設定も可能です。以下に例を示します。
#:sdk Microsoft.NET.Sdk.Web
#:package WeihanLi.Web.Extensions@2.1.0
#:property ManagePackageVersionsCentrally false
using WeihanLi.Web.Extensions;
var app = WebApplication.Create(args);
app.MapGet("/", () => "Hello World!");
app.MapRuntimeInfo();
await app.RunAsync();
同様に dotnet run webapi.cs を実行します。

スクリプトが複雑になり、さらにカスタマイズが必要になった場合、ファイルプログラムを使いたくないときは、1つのコマンドで標準プロジェクトに変換できます。CLI が自動的に
.csprojファイルを生成し、関連設定を移行するため、コードの動作は変わりません。
dotnet project convert webapi.cs
変換後のプロジェクトは以下のようになります。`dotnet run` で直接実行することも可能です。

Linux/Unix の shebang(`#!`)にも対応しており、C# スクリプトを Bash/Python のように直接実行できます。`./hello.cs` で実行可能です。
```csharp
#!/usr/bin/dotnet run
Console.WriteLine("Hello, .NET!");

将来の機能
dotnet run file.cs で C# ファイルを直接実行する提案は、.NET に柔軟で強力なスクリプト体験をもたらします。設計ドキュメントでは、ファイルベースプログラムを .NET エコシステムでより実用的にするための、多くの将来の拡張が展望されています。今後追加される可能性のある機能は以下の通りです。
1. ターゲットパスの拡張サポート
- フォルダをターゲットに: フォルダを
dotnet runのターゲットとして指定可能に(例:dotnet run ./my-app/)。そのフォルダ内のメインエントリポイントを直接実行できます。 - 標準入力とインラインコード:
dotnet run --cs-from-stdinで標準入力から C# コードを読み取ったり、dotnet run --cs-code 'Console.WriteLine("Hi")'でコードを直接文字列として指定して実行できるようになります。
2. 統一されたコマンドライン引数
- ディレクトリとファイルオプション:
--directory、--file、または統一された--pathオプションを導入し、ファイルプログラムとプロジェクトプログラムで一貫したコマンド体験を提供します。 - 複数エントリポイントのサポート:
--entryなどのパラメータを追加し、複数プログラムがあるディレクトリから特定のエントリポイントを指定して実行できるようにします。
3. 統合と一貫性の強化
- 成長前後のシームレスな体験: ファイルプログラムの場合でも、プロジェクトにアップグレードした場合でも、
dotnet runなどのコマンドがスムーズに動作することを保証します。 - 共通オプション: プロジェクト形式とファイル形式の両方に適用できる統一パラメータを提供し、形式間の移行をよりスムーズにします。
4. パフォーマンスと使いやすさの向上
- ファイルの選択的包含: パラメータやディレクティブで含めるファイルを制御できるようにし、不意に大量のファイルが含まれてしまうことによる問題やパフォーマンス負荷を軽減します。
- ネストされたファイルのエラー通知: サブディレクトリに多数の
.csファイルや.csprojファイルが含まれている場合、警告やエラーを表示して、意図しない大量コンパイルを防止することを検討します。
5. 複数エントリポイントシナリオの実装最適化
- プロジェクト構造の生成: 複数エントリポイントを持つディレクトリがプロジェクトに「成長」する際の構造生成を最適化し、プロジェクトサブディレクトリを適切に分割し、コード共有をより明確にします。
- 高度なアクセス制御:
InternalsVisibleToなどの機能をコード共有に活用する方法を探り、将来の C# 言語機能の強化も検討します。
6. Shebang とシェルサポート
- 専用実行可能ファイル:
dotnet-runやdotnet-run-fileのような専用の実行可能ファイルがリリースされる可能性があり、さまざまなシェル環境での shebang(#!)の互換性が向上し、スクリプトのクロスプラットフォーム直接実行が可能になります。 /usr/bin/envのサポート: shebang 使用時のシェルによる引数渡しの制限を回避し、CLI スクリプトの使いやすさを向上させる方法を研究します。
7. ファイルプログラム対応コマンドの拡充
- ビルドと復元:
dotnet restore file.cs、dotnet build file.csなどのコマンドを拡張し、IDE や CI でのファイルプログラムの統合を容易にします。 - パッケージ管理:
dotnet package addを C# ファイルの先頭に#:packageディレクティブを追加する操作に直接対応させ、スクリプトの依存関係管理を簡素化します。
8. 明示的なファイルインポート
- インポートディレクティブ: 将来、
#import ./another-file.csのようなディレクティブをサポートし、含める C# ファイルを明示的に指定できるようにすることで、開発者によるより柔軟な制御を実現します。
さらに
現時点では dotnet run hello.cs を使用する必要がありますが、将来的には dotnet hello.cs のように簡略化される可能性があります。また、コードを直接文字列として実行することもできるようになります。今後のより便利な機能に期待しましょう。
詳細については、公式ドキュメントをご参照ください。https://github.com/dotnet/sdk/blob/main/documentation/general/dotnet-run-file.md
少し残念な点としては、新しい NuGet パッケージ参照構文が追加されたことです。dotnet-script の nuget: package@version とは異なり、互換性がありません。
現時点ではカスタムエントリポイントはサポートされていませんが、今後サポートされればさらに便利になるでしょう。期待しています。
最後に、build カンファレンスで dotnet run file に関する紹介動画があります。興味があればご覧ください。
【動画は元のWeChat公式アカウントでご確認ください】
参考資料
- • ドキュメント:https://github.com/dotnet/sdk/blob/main/documentation/general/dotnet-run-file.md
- • ファイルベースプログラム IDE 仕様:https://github.com/dotnet/roslyn/blob/main/docs/features/file-based-programs-vscode.md
- • Unix における Shebang:https://en.wikipedia.org/wiki/Shebang_(Unix)
- • https://github.com/dotnet/sdk/pull/46915/files
- • https://github.com/dotnet/sdk/pull/48782/files
- • https://github.com/dotnet/sdk/pulls?q=is%3Apr+label%3AArea-run-file+is%3Aclosed