.NET Interactive で C# と PowerShell を股に掛ける

Pocket

この記事は、「C# Advent Calendar 2020」 9日目の記事、かつ 「PowerShell Advent Calendar 2020」 9日目の記事だ。

スミマセン。横着した。

この時期になれば .NET Interactive の Preview 4 が出てるだろうしその記事でも書こうかな~ などと目論んでいたものの、 残念ながら登場しなかった。

このため、 .NET Interactive .NET 5 対応版の導入と、 Variable sharing の内容でお茶を濁そうと思う。

.NET Interactive のなんたるかについては、以前の以下の記事で取り扱っているので、そちらを参照願いたい。

.NET Interactive を .NET 5 で動かしてみる

いきなり本題とは関係ない話になるが、 せっかく .NET 5 がリリースされたところなので、 .NET Interactive を .NET 5 で動かしてみよう。

12/8 現在、NuGet で公式にリリースされている .NET Interactive は、 9月にリリースされた Preview 3 に少し更新が加えられた、 1.0.155302 だ。
これは、 .NET Core 3.1 上に構築されている。

一方で 11/27 頃のビルド (dotnet/interactive@61d2315) あたりでは、既に .NET 5 対応が済まされている。

更に、 何故か Visual Studio Code の .NET Interactive Notebooks 拡張では、 .NET 5 に対応した 1.0.160204 がリリースされている。

このため、 現時点で .NET Interactive で .NET 5 を扱う主な方法は、以下の通り。

  • launch binder main ブランチの binder コンテナにアクセス
  • Azure DevOps の CI ビルドの NuGet feed (dotnet-tools) から、 Glogal Tool を DL
    • 実行例:
      dotnet tool install -g Microsoft.dotnet-interactive --version 1.0.160204 --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json
  • VS Code Insider を起動し、 .NET Interactive Notebooks 拡張の Preview をインストール

残念ながら、 .NET Interactive インストール済み Jupyter の docker イメージのようなものは 公式では用意されておらず、 コンテナを使いたかったら自分でビルドするしかない。
(そのせいで、 上記 binder の起動は遅い)

vscode 拡張だと、 コード補完が ignore case で効くのでとても書きやすい。
以下、 vscode の .NET Interactive Notebooks 拡張の バージョン 1.0.160204 での実行を前提とするが、 他の環境でも同様に動作するはずだ。

なお、 起動した Notebook やコンソールの .NET CLR のバージョンを知りたければ、 System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription を実行すれば良い。
.NET 5.x.x と表示されれば、 .NET 5 で起動していることが確認できる。

Variable sharing とは

さて、ようやく本題。

.NET Interactive が面白いのは、 ひとつの Notebook 内で、 C#, PowerShell, F# の言語間の変数を共有できる点だ。
悪いなあ、 VB.NET。 このツールは3人用なんだ。

この変数を共有できる機能を、 variable sharing という。

使い方はとても簡単で、 #!share --from マジックコマンドで、 参照する .NET カーネルと変数名を指定するだけだ。

但し、 読み込まれている型の空間は共有されない点には注意だ。
例えば、 C# で定義したクラスのインスタンスを PowerShell で読み込もうとしたり、
PowerShell でロードされているモジュールで定義された型のインスタンスを C# で読もうとすると、エラーになってしまう。
詳しくは、 interactive/variable-sharing.md · dotnet/interactive のドキュメントを参照。

但し、 PowerShell でよく使われる PSCustomObject 型については特別対応が入っているらしく、いい感じに Dictionary<string, object> に変換されて C# でも扱える。
なにそれ。 PowerShell 内部でも欲しい機能なんだけど。

Variable sharing の使いどころ

例えば…
例えば……
………

うーん、よい例が思いつかない…

そもそも、 C# でできることはだいたい PowerShell でできるし、 その逆もまた然りなんだよな。
加えて PowerShell では、 Add-Type で手軽に C# のコードを埋め込めるし…

強いて挙げるなら、 PowerShell は、付属のコマンドレットや追加モジュールによって、 I/O 操作やリソースの読み込みにが強い一方で、 パイプを交えたデータの処理はだいぶ遅いところだろうか。
例えば、 PowerShell で ファイルの読み込みなどを行いつつ、 大量のデータの処理は C# で行うといったような使い方はアリかもしれない。

#!pwsh
$data1 = Get-ChildItem *.json -Recurse | Get-Content -Raw | ConvertFrom-Json;
$data2 = Get-Clipboard;
#!csharp
#!share --from pwsh data1, data2
data1.Where(kv => kv.Key == "tools")
#!csharp
data2.First()

この程度のデータ処理なら PowerShell で全く問題ないレベルだが、 処理するデータの数が増えてくれば C# で実行するメリットが出てくるだろう。

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください