【C#】Roslyn for Scripting C#小ネタ集【Script】

Pocket

タイトル通りちょっとしたネタの詰め合わせです。

 

Roslynの一部でありスクリプトとしてのC#をサポートするRoslyn for Scriptingの具体的な小ネタ紹介です。Roslyn for Scripting自体の基本的な使い方は前に書いた記事をご覧ください。

 

もくじ

 
 

基本的な準備

適当に用意します。インストール周りでうまく行かない場合は前回の記事を見て下さい。

  1.  コンソールアプリケーション作ってターゲットを.NET 4.6に設定
  2.  NuGetでMicrosoft.CodeAnalysis.CSharp.Scriptingをインストール(2015/11時点ではプレリリース版しか無い事に注意)
  3.  実行ディレクトリ(bin\Debugとか)に”test.csx”というソースファイルを配置
  4.  コンソールアプリケーション側のプログラムを下記のようにする

本記事の前半では本体側のコードをコレで放置し、スクリプト側”test.csx”の中を書き換えて色々試します。

 
 

System.Linq使おうとしたらエラーになったんだけど

C#をスクリプトで使うならLINQ使いたいのは当然ですね。そこで”test.csx”を次のように書いて実行してみます。

しかしコレだけだと実行時にスクリプトのコンパイルエラー(CompilerErrorException)が吐かれて止まります。

エラーが起きた原因は何かというと、デフォルトのRoslyn for Scriptingではスクリプトが参照するDLLが最低限しか設定されておらずLINQを実装してる”System.Core.dll”への参照が無いためです。解決策としてはシンプルに、スクリプトの最上部に#rディレクティブでDLL参照を追加するだけでOKです。

今度は正しく動作します。

 
 

async/awaitまわりの扱い

スクリプトとasync/awaitに関して唯一かつ最大のポイントは「スクリプトのベタ打ち部分でawaitが普通に使える」という点です。例えばスクリプト自身のソースファイルを非同期で読み込んで文字数を拾うコードは次のように書けます。

もちろんこの例だとasync/awaitのメリットがあんま無いですが、awaitが普通に使えてる事自体は分かりますね。

 
 

拡張メソッドって普通に定義できんの?

これは「プログラム本体側のコードからスクリプトに渡したAPIをスクリプト側で拡張したい!」というケースで便利そうなので記載してみました。拡張メソッドについてはクラスで囲わずに直接メソッドを書けば作れます。クラスで囲うのはダメです。

具体例としてstringを拡張して使ってみます。以下はOKな書き方の例です。

一方ダメな例はこちら。

これだとエラーで怒られます。エラーについてもうちょい詳しく知りたい方は下記の補足をどうぞ。

補足(クリックで展開)

ダメの方のエラーについてですが、具体的な内容としては「入れ子クラス内で拡張メソッド定義すんじゃねえ!」という主旨のエラーが出ます。「入れ子クラスなんか書いた覚えないよ?」と思うかもしれませんが、実はスクリプトをコンパイルするとスクリプト全体がクラス定義で囲まれるため、スクリプト内部でクラスを定義した場合入れ子クラスとなります。

 

更に詳しく確認したい場合、コンパイルが正しく通ったとき実際に生成されるコードをILSpyとかで見るのがオススメです。まずMain関数をちょっと書き足し、コンパイル結果をdllとして保存します。

これで実行ディレクトリに”test.dll”が出力されるのでILSpyで中を見た結果が下記です。これは上に記載されている拡張メソッドを用いたスクリプトのうち、ビルドが通ってる方のケースです。(※ちなみにビルドが通らないスクリプトでdllを保存すると容量ゼロのファイルになります)

 
 

スクリプトの中でstatic変数の宣言したらどうなるの?

先に注意しておきますが、本節の内容は他の節と異なり「アレ、この仕様って大丈夫なの…?」と疑問に思ったので書いたネタです。まずスクリプトをこのように書きます。

次に本体側のMain関数を次のように書き換えます。

ふたつの方法でスクリプトを実行しています。前者ではScriptのインスタンスを毎回作り、後者では同じインスタンスを使いまわすのが違いですね。実行結果はこうなります。

結果から分かる通り、同じScriptのインスタンスを使いまわせばstatic変数のデータが保持できることが分かります。

これは便利そうにも見えますが、Roslyn for Scriptingでは色々なクラスがImmutableに作られてる事を考えると、上の例は「Scriptインスタンスにstatic変数の中身が付きまとう事で不変性にヒビが入りました」と解釈した方がいいように見えてしまい、なんだか居心地が悪いです。特に理由が無いなら避けるべき書き方だと言えます。

 
 

dynamicキーワード使うとスクリプト感が高そう

小ネタ集のトリを飾るのはスクリプト感の高いキーワードであるdynamicです。C#とはいえスクリプトで使う以上は静的型付けしたくないシチュエーションもあるので、さっそくdynamicが使えるか試してみます。

本体側のコードをこんな風に書き足します。

スクリプト側はこうします。

dynamicキーワードを使うためにはSystem.CoreとMicrosoft.CSharpの参照が必要なことに注意してください。これで実行すると普通に動作し、dynamicキーワードが正しく使えることが確認できます。

 

まとめ

安定版が欲しいです。

 

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です