C# の REPL, スクリプティング環境の比較

この記事は、 [C# その2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/c-sharp-2) の 12/4 の記事だ。
ギリギリの投稿で申し訳ない。

Qiita が怖いので、 普段は [ブログ](https://aquasoftware.net/blog/) や [Crieit](https://crieit.net/), [Qrunch](https://qrunch.net/) に投稿しているのだが、 今回はせっかくの Advent Calendar なので、 Qiita 初投稿。
お手柔らかにお願いします。

[Qiitaとブログの使い分け](https://qiita.com/hal7pi/items/8bf34c95424c1e2248ff) 、難しいよね。

**追記 2019/12/06**
ktz_alias 氏にコメントで教えてもらった JupyterLab がなかなか良かったので、その情報を追記した。


## みんな C# の REPL に何を使ってる？

頭の中で正確にコードをコンパイルして動かせる人ならともかく、 私のようにコードを書くのが本職ではない人間にとっては、 コード片が意図通り動くかどうかを対話的に入力できる環境があるとありがたい。

また、細々した処理を行いたいとき、 プロジェクトを作成せずにサクッと実行できるとうれしいだろう。

皆は、どのような C# REPL 環境を使っているだろうか？

**…そうだね、 Visual Studio の C# Interactive だね。**

～～糸冬～～

&nbsp;

…それで、終わってしまってはナンなので、 C# の REPL や スクリプト実行 ができるツールを紹介しつつ、簡単に比べてみたいと思う。

「他にもこんなものがあるよ！」 と言うのがあったら、是非コメントいただけると幸いだ。


## Visual Studio C# Interactive

![csharp_interactive.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308278/19e8143b-2c41-aab9-69d4-84cb9b56df2d.gif)
[Visual Studio](https://visualstudio.microsoft.com/downloads) に付属している、C# インタラクティブ。

正直、これが使えるならこれ一択という感じ。

他がぱっとしないのも、これが強すぎるからかもしれない。

最大の問題は、ライセンスだ。
Visual Studio Community があるので、 個人PC上で個人用途に限るなら何も問題はないが、企業や団体に所属したり、それらから受託する場合はそうはいかない。
せっかく Visual Studio 2017 Professional を買ってもらえても、 2019 が出た後は最新の C# が使えなくて悔しい思いを味わうことになる。

他にも、 ちょっとコードの実行を試したいだけだと、立ち上げるのが重量級過ぎるという問題もある。
（これは、貧弱すぎるスペックのマシンを使っているのが悪いというのもあるが。。）

また、現状は .NET Framework のみの提供で、 .NET Core 環境が無いというのも地味な欠点。
C# 8.0 以降、 .NET Core 3 (厳密には、 .NET Standard 2.1) 以降じゃないと使えない機能がぼちぼち出てきているので、これは意外と大きな問題である。

C# Interactive には、 Visual Studio を立ち上げないでもよいコンソール版 (csi.exe) が存在するのだが、こちらはコード補完が全くないので利便性が大きく落ちる。


## Mono C# Shell csharp, gsharp

![csharp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308278/493f92e4-6fb1-c0df-c7c4-67a10cc7b7f3.gif)
![gsharp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308278/2384b41f-70eb-c4ac-be53-71f69915f40e.gif)
[Mono](https://www.mono-project.com/download/stable/) に付属している C# Shell の CUI版 と GUI版。

.NET Core が登場してからは何かと影が薄い Mono。

Xamarin や Unity のバックエンドとしてはまだまだ現役で使われているけれど、 .NET 5 では .NET Core と統合される予定。

そんな Mono には、付属の C# Shell が用意されている。

C# Interactive には遠く及ばないものの、簡単なコード補完もついているので、ちょっと動かす程度なら全然使える。
ただ、 型の補完が微妙だったり、 CaseSensitive な補完しかできなかったり(これは好みにもよるが)、 補完の候補が一部足りてなかったりと、 あまり期待しない方がよいレベル。。。

GUI 版は、 Mono 5 以降ほとんど更新されていないので、 補完のインターフェースが CUI版 よりもちょっと悪い。
一方で、 Plot 関数でグラフが描けたり、 画像を表示できたりといった、 使いどころが微妙な利点がある。

また、 Windows版 Mono には GUI 版である gsharp が入っていない。
このため、 WSL に Mono を入れて Xサーバ で GUI を動かすのが手っ取り早いのだが、 Ubuntu で 最新 (6.4系) の Mono の gsharp を入れようとすると、 パッケージの依存関係の不具合でインストールできない問題がある。
→ [C# REPL GUI Shell, Mono gsharp を Ubuntu に入れようとすると発生するエラーを回避する | Aqua Ware つぶやきブログ](https://aquasoftware.net/blog/?p=1237)


## dnSpy

![dnspy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308278/e09350f5-be47-b040-b973-2ac09683bb59.png)
お世話になっている人も多いだろう、 多機能で UI がステキな .NET の 逆コンパイラ・デバッガーである [dnSpy](https://github.com/0xd4d/dnSpy)。

実はこの dnSpy にも C# Interactive が付属している。

シンタックスハイライトもきれいに効いて、とてもイケているのだが、大変残念ながらコード補完がないのだ。
一応かなり昔から作者による Issue は立っているのだが、 毎回マイルストーンが後ろにずらされ、最近ついにマイルストーンから外されてしまったので、対応は期待できなさそうだ。
[Add C# REPL completion · Issue #197 · 0xd4d/dnSpy](https://github.com/0xd4d/dnSpy/issues/197)

.NET Core 版の dnSpy なら、 C# Interactive も .NET Core で動いているのが良ポイント。

ただ、残念ながら Linux などの 非Windows では提供されていない。


## LINQPad

![linqpad.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308278/cdc76ab6-9c2a-3a17-acf0-1cb73c443cf3.png)
[LINQPad - The .NET Programmer's Playground](https://www.linqpad.net/)

LINQ に限らず、 C# や VB.NET のコードの動作確認を行えるツールだ。

コードは書いたそばから自動的に実行されて結果が表示されるが、 REPL ではないため、毎回コードの先頭から実行される。
このため、使い勝手としては C# Script に近い。

データのダンプ機能が優れているので、簡単なデータ処理をさせるのには向いているかも知れない。


## CS-Script

[CS-Script | ECMA-compliant C# based scripting platform.](https://www.cs-script.net/)

わりと C# が登場した (2002年) 直後くらい (2004年) から存在している、老舗スクリプティング環境。

スクリプトファイルを指定してコードを実行することはできるが、 どちらかというとアプリにライブラリとして組み込むスクリプトエンジンを提供することに主眼を置いているようだ。

他のほとんどの実装が Roslyn のスクリプティング機能で動いている一方、 CS-Script は独自のエンジンで動かしているようだ。
…とはいっても、最終的には .NET や Mono の Roslyn コンパイラでコンパイルされるわけだけども。

その為かどうかわからないけど、スクリプトの記述ルールが他とちょっと違う。


## scriptcs

![scriptcs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308278/59e67586-a8d3-73c3-1673-a69b49a8e3f2.png)
[scriptcs - Write C# scripts in your favorite text editor](http://scriptcs.net/)

こちらも Roslyn がスクリプティング機能に対応する前の、割と昔からある老舗。

CS-Script とは異なり、コチラは Roslyn 登場後は Roslyn スクリプティング機能で動いているようだ。

スクリプトを実行したり、 REPL を起動できたりはするが、 コード補完はできないし、これといった特徴がない。。。

.NET Framework で動作するため、 .NET Standard 2.1 にも非対応。


## dotnet script

![dotnet-script.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308278/35c3e030-099d-cf63-7234-6e6ba3531ad2.gif)
[filipw/dotnet-script: Run C# scripts from the .NET CLI.](https://github.com/filipw/dotnet-script)

C# スクリプト実行環境その3．

Visual Studio Code と連携することで、 デバッグや OmniSharp のコード補完のメリットが享受できる。
スクリプトを書いて実行するなら、個人的にはコレがオススメ。

また、 nuget と連携して依存ライブラリの解決が簡単にできるのも強み。

REPL はあるが、 コード補完はないのでオマケ程度と考えれば。


## .NET Core with Jupyter Notebooks

![jupyter.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308278/6b02b3ac-355d-3ccc-8e5a-ffb4c0333d67.gif)

@ktz_alias 氏にコメントで教えていただいた JupyterLab + .NET カーネル ([.NET Core with Jupyter Notebooks](https://devblogs.microsoft.com/dotnet/net-core-with-juypter-notebooks-is-here-preview-1/)) が、なかなか素晴らしい REPL 体験を提供してくれる。

型に基づいたコード補完が REPL で使えるのが最の高。

ローカルに Webサーバー 立ち上げてアクセスする仕組みなので、 Windows でなくても利用できる。

Preview 版と言いつつも、すでにだいぶ完成度が高いので、 「タブキー押さなくても、 "." を入力したときに補完が働いてほしい」 とか 「補完時には大文字と小文字を区別しないでほしい」とか、細かい部分が逆に気になり出してしまうほど。
今後の更新が楽しみである。

ドキュメントでは Jupyter インストールするために Anaconda 入れろとか書いてあるけれど、 Jupyter で .NET Core カーネルを実行する分には Python + pip で十分だ。
pip で Jupyter をインストールする場合、依存パッケージが膨大なので、venv で仮想環境に分けておいたほうが良い。
雑になるが、おおむね以下のような手順でインストール可能。

1. [.NET Core SDK 3.1 LTS](https://dotnet.microsoft.com/download/dotnet-core/3.1) または [2.1 LTS](https://dotnet.microsoft.com/download/dotnet-core/2.1) をインストール
1. `dotnet tool install -g dotnet-try` で dotnet-try グローバルツールをインストール
1. [Python 3.7 あたり](https://www.python.org/downloads/release/python-375/) をインストール
1. venv 環境を作成して、 pip で jupyterlab をいれて、 .net jupyter カーネルを入れて、 JupyterLab を起動 

Windows なら以下のような感じ。

```cmd
py -3.7 -m venv .\venv_jupyter
.\venv_jupyter\Scripts\activate
pip install jupyterlab
dotnet try jupyter install
jupyter lab
```

Ubuntu なら以下のような感じ。

```bash
python3 -m venv ./venv_jupyter
. ./venv_jupyter/bin/activate
pip install jupyterlab
dotnet try jupyter install
jupyter lab
```

私が試した限りにおいては、 Python 3.8 だとエラーが出て Jupyter が起動できなかった。


## オマケ

C# じゃないけど、 .NET で REPL できるヤツら。

* [PowerShell](https://docs.microsoft.com/en-us/powershell/)
    * 言わずと知れた、 .NET 界の コマンドラインシェル＆スクリプト。  
    オプジェクトパイプラインという独特な仕様と PowerShell Core の登場によって、 Windows 外にも地味に浸食しはじめている。  
    C# の動作確認ではなくて、 .NET ライブラリの動作確認を行いたいのなら、 PowerShell で十分だろう。  
    C# と文法が若干似ているのも使いやすいポイント。 似ているのに所々全然違うので慣れるとかえってハマったりもするが。  
    C# でできることは大体 PowerShell でもできるが、オーバーロードやジェネリックスの解決がちょっと苦手。
* F#
    * 公式でまともな REPL (fsi.exe) が提供されているので、 こちらも .NET ライブラリの動作確認を行いたいなら代替になる。  
    関数型言語で C# とはかけ離れた文法なので、知らんと全く読み書きできない。
* [IronPython](https://ironpython.net/)
    * Python が得意ならコレも選択肢になるだろう。  
    Python らしく、 REPL もそこそこ使える機能を持っている。  
    .NET Core (.NET Standard 2.0) にも対応している。  
    言語仕様が、 2020年1月1日 で命日を迎える 2.7 系なのが難点。  
    現在開発中の IronPython3 では Python 3 に対応されるので、花開くかもしれない。


## まとめ

ここまで挙げたものの特徴を表にしてみた。

|種類|スクリプティング|REPL|.NET Standard 2.1 対応|Linux対応|コード補完|備考|
|:--|:--|:--|:--|:--|:--|:--|
|C# Interactive|○|○|×|×|◎|商用利用有償 Mac版ならある|
|Mono C# Shell|○|○|○|○|○|GUI版 は WSL 経由|
|dnSpy|○|○|×|×|×| |
|LINQPad|○|×|×|×|×| |
|CS-Script|○|×|○?|○|×|老舗|
|scriptcs|○|○|×|×|×| |
|dotnet-script|○|○|○|○|△|コード補完はスクリプト記述時のみ。 NuGet 連携が特徴。|
|JupyterLab|○|○|○|○|○| |
|PowerShell|○|○|○|○|○| |
|F#|○|○|○|○|○| |
|IronPython|○|○|○|○|○|次期 2.7.10 で .NET Core 3.0 に対応予定|