【C#】`dotnet run file.cs` で実行できるようになるらしい
どういうこと?
- .NET 10では
dotnet run file.cs
でC#が実行できるようになる(らしい)- .NET SDK 10 preview4の時点で使える
dotnet run file.cs
-
dotnet run
やdotnet build
とは違い/bin
や/obj
が生成されない- ビルド成果物・中間物は作られません
-
通常のソース+プロジェクトファイルの形式にあとから変換できる
dotnet project convert file.cs
-
C# 14.0?にも新しい記法が入る模様
#!/usr/bin/dotnet run
#:sdk Microsoft.NET.Sdk.Web
#:property TargetFramework net10.0
#:property LangVersion preview
#:package System.CommandLine 2.0.0-*
Console.WriteLine("Hello, World!");
- 昔からある「C#スクリプト(拡張子が
*.csx
のヤツ)」とは別物
dotnet run file.cs
これまでの dotnet run
昔からあるdotnet run
コマンドはC#[1]の依存関係の解決・コンパイル・実行をまとめてやってくれる便利なコマンドです。
C#といえばコンパイル結果の実行ファイルを共有する、というイメージが強いですが、dotnet run
コマンドがあるので、(SDKがインストールされている環境なら、)スクリプト配布のようにソースコードをそのまま配布してつかうこともできました。
ただし、これまでのdotnet run
コマンドはソースファイル(*.cs
)以外にプロジェクトファイル(*.csproj
)が必要でした。
dotnet new console
でテンプレートから作れば自動で作られるとはいえ、ファイルがたくさんあるのはスクリプト的な使い方をするには不便です。
ソースファイル(*.cs)を直接指定できるように
.NET 10以降のdotnet run
コマンドではソースファイルを指定して実行できるようになります。プロジェクトファイル(*.csproj
)は不要です[2]。
dotnet run file.cs
コマンドライン引数の指定の仕方はdotnet run
と同じで、ソースファイル指定以外の引数がargs
に渡されます。
dotnet run file.cs --option=xxx
ソースファイルを指定しなければ前と同じ挙動(プロジェクトファイルを探して利用)になります。
bin
/obj
)は生成されない
ビルド成果物・中間物(通常のdotnet runやdotnet buildではビルド結果(dllとかexe)や中間成果物が同じディレクトリの/bin
や/obj
に生成されます。
しかし今回の dotnet run file.cs
ではビルド結果や中間物は生成されません。
exeもdllも存在せず、そのまま実行されます。ちょっとスクリプトっぽいですね。
とはいえビルドしていない訳ではなく、初回は依存関係のチェックもあるのでそこそこ時間が掛かります(初めてdotnet runを実行したときと同じくらい)。さすがにスクリプトほど早くはないです、残念!
/bin
や/obj
が作られないのでgitignoreに指定ミスってコミットしてしまった、というミスも防げますね[4]!
指定できるソースファイルは?
実行できるソースファイルはエントリポイントになれるファイルです。
エントリポイント、と言っても今のC#はトップレベルステートメントがあるので、
要はスクリプトみたいにいきなりコードが書かれてるソースファイルであればエントリポイントになります。
Console.WriteLine("Hello, World!");
エントリポイントじゃないcsファイルを指定すると、失敗します。
CSC : error CS5001:
プログラムは、エントリ ポイントに適切な静的 'Main' メソッドを含んでいません
プロジェクト "lib.csproj" のビルドが終了しました -- 失敗。
The build failed. Fix the build errors and run again.
//これはエントリポイントじゃない
public class Lib {}
C#の新しい記法: ignored directives
C#にも新しい記法が追加される予定です。
正確には2つあり、次の記号の組み合わせで始まる行はC#のコードとしては無視されます。
-
#!
で始まる shebang directive -
#:
で始まる ignored directive
#!/usr/bin/dotnet run
#:sdk Microsoft.NET.Sdk.Web
#:property TargetFramework net11.0
#:property LangVersion preview
#:package System.CommandLine 2.0.0-*
これらの行の前には文字を書くことはできません(BOMもNG)。
#!/usr/bin/dotnet run
#:sdk Microsoft.NET.Sdk.Web
#:property TargetFramework net11.0
#:property LangVersion preview
#:package System.CommandLine 2.0.0-*
Console.WriteLine("Hello, World!");
error CS1040: プリプロセッサ ディレクティブは行でスペース以外の最初の文字でなければなりません
プロジェクト "badignore.csproj" のビルドが終了しました -- 失敗。
C#のコードとして意味がなく、コンパイラやMS Buildなどに情報を与える用の記法になります。ここにcsprojで記載していた内容を書くことで、csprojが不要になります。
#!
(shebang)
shebang directiveはシェルスクリプトなどでおなじみかと思います。
#!/usr/bin/dotnet run
つまりunix環境でパスを指定し、chmodすることでcsファイル単体で実行できるようになります。
【追記】macOS Sequoia 15.5の場合
#!/usr/bin/dotnet run
では動きません。
サンプルソース中の1行目は以下に書き換えます。
- #!/usr/bin/dotnet run
+ #!/usr/bin/env -S dotnet run
あとは実行権限を与えれば(chmod 755)、csファイルの指定だけで実行できます。
% chmod 755 file.cs
% ./file.cs
Hello, World!
#:
記法としては行頭の#:
だけが追加されています。
しかし実際には#:sdk
や#:property
のように#:
に続けてcsprojで記載していた内容を書くことになります。
記法 | csproj |
---|---|
#:sdk *** |
<Project Sdk="***"> |
#:property XX YY |
<PropertyGroup><XX>YY</XX></PropertyGroup> |
#:package XX 1.0.0-* |
<ItemGroup><PackageReference Include="XX" Version="2.0.0-*" /></ItemGroup> |
今のところ指定できるのはsdk
,property
,package
の3つだけのようです。
通常のcsprojに変換できる
次のコマンドで普通のソースファイル(*.cs
)とプロジェクトファイル(*.csproj
)からなる普通の形式に変換できます。
dotnet project convert file.cs
file.cs
↓
file/
├ file.cs
└ file.csproj
ignored directivesの記載があった部分はソースファイルから削除され、csprojに変換されます。
#!/usr/bin/dotnet run
#:sdk Microsoft.NET.Sdk.Web
#:property TargetFramework net11.0
#:property LangVersion preview
#:package System.CommandLine 2.0.0-*
↓
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net11.0</TargetFramework>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.CommandLine" Version="2.0.0-*" />
</ItemGroup>
</Project>
C# Script / Replと何が違う?
C#には昔からC# Script(Roslyn Script)というスクリプト実行の仕組みがありました[6]。
- dotnet interactive
- VSCodeのPolyglot Notebooks
-
dotnet tool
でインストールできる外部ツール
C# Scriptは名前の通りスクリプト実行なので、今回のものとは次の違いがあります
- ファイルの場合は専用の拡張子(
.csx
)が必要 - 外部ライブラリ参照などで
#r
等の専用記法が必要 dotnet run file.csx
はできない
一方、dotnet run file.csのC#は普通のC#のソースコードです。
ignored directivesも必要なければ書く必要なく、これまでのC#のソースそのままが使えます。
ビルドにはやや時間がかかるため、スクリプトほどは早く動作せず[7]、REPL用途には向いてません。
他小ネタ
-
dotnet restore file.cs
やdotnet build file.cs
もできるとドキュメントにありますが、.NET SDK 10.0-preview4では動きませんでした。- 正式版では入る?
-
dotnet pack file.cs
やdotnet watch run file.cs
はサポートしない方針だそうです-
watch
は欲しくなりそうな気も…
-
-
*.cs
の拡張子のファイルだけが対応しているようです[8]- F#とかVB.NETはサポートの想定がないのかもしれません
- まあF#には
dotnet fsi
ありますから要らないかも
- まあF#には
- F#とかVB.NETはサポートの想定がないのかもしれません
-
-bl
でバイナリログを出力するオプションが有効のようです - 追記:ビルドの高速化が検討されているようです
-
dotnet file.cs
で実行できるようになる事も検討されているようです
まとめ
- (たぶん).NET 10では
dotnet run file.cs
で単一ファイルからC#を実行できるようになり、プロジェクトファイル(.csproj
)が不要に - ビルド成果物・中間ファイル(
/bin
や/obj
)が生成されない - 実行は通常のC#コードと同様(スクリプトではない)ため、既存のC#の知識がそのまま活かせる
- 新たに導入される
#:
や#!
のディレクティブ記法でcsファイル内で依存関係やSDK指定が可能に -
dotnet project convert file.cs
で通常のプロジェクト構造に変換可能 - 既存のC# Script(
.csx
)とは別物 - 現時点[9]では.NET SDK 10のプレビュー版で利用可能
追記
参考
- sdk/documentation/general/dotnet-run-file.md at main · dotnet/sdk
- csharplang/proposals/ignored-directives.md at main · dotnet/csharplang
-
正確にはF#なども ↩︎
-
内部的には仮想的なプロジェクトファイルが作られるような動きになるそうです ↩︎
-
dotnet new gitignore
すればいいだけですが… ↩︎ -
preview4時点では未実装 Support multiple files in file-based programs by jjonescz · Pull Request #48782 · dotnet/sdk ↩︎
-
なお、ややこしいですがUnityのC#も「C# Script」と言われていますがまた別物です ↩︎
-
とはいえdotnet-scriptも初回は同じくらい時間かかります ↩︎
-
2025-05-23 ↩︎
Discussion