BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース C# 9 - ソースジェネレータのためのパーシャルメソッド拡張

C# 9 - ソースジェネレータのためのパーシャルメソッド拡張

ブックマーク

原文(投稿日:2020/06/05)へのリンク

C# 9のソースジェネレータ(Source Generator)は、コンパイル時にコードを調査して追加的にソースコードを挿入するようなコンパイラ拡張を可能にする。挿入されたコードは、コンパイルされたものとまったく同じアセンブリに組み込まれる。この機能を活用するためにMicrosoftは、パーシャルメソッドの制限の大部分を撤廃することにしている。

パーシャルメソッド(Partial Method)は2007年に、ソースコードジェネレータの機能を拡張する目的でVBとC#に導入された。基本的な考え方は、ソースコードジェネレータがパーシャルメソッド(partial method)を起動するコードを出力する、というものだ。生成されるコードの動作を修正したい場合、開発者はパーシャルメソッドを実装することができる。それ以外の場合は、パーシャルメソッドは、そのメソッドの呼び出しとともに削除される。

ソースジェネレータでは、このストーリが逆転した。開発者が最初に、デザインするパーシャルメソッドを定義する。ソースジェネレータがそのパーシャルメソッドを確認すると、周辺情報と外部情報を組み合わせてそれを実装する。例えば、パーシャルメソッドの属性とデータベースのスキーマを組み合わせることで、データベースを呼び出す完全なSQLを持ったメソッドを生成することが可能になる。

現時点のパーシャルメソッドには、次のようないくつかの制限がある。

  • パーシャルメソッド宣言の戻り値はvoidでなくてはならない
  • パーシャルメソッドのパラメータはoutではなく、inまたはrefでなければならない
  • パーシャルメソッドは暗黙的にprivateであり、従ってvirtualにはできない

最初のパーシャルメソッド拡張プロポーザルにより、これらの制限が撤廃されることになった。その理由について、プロポーザルでは次のように説明している。

これにより、パーシャルメソッドが参加可能なソースジェネレータのシナリオセットが拡張され、結果としてソースジェネレータの機能と適切にリンクするようになります。例えばregexは、次のようなパターンを使って定義できます。

[RegexGenerated("(dog|cat|fish)")]
partial bool IsPetMatch(string input);

このように、ジェネレータにオプトインする宣言方法がシンプルになると同時に、ジェネレータがソースコードを探索してコードを生成するための宣言セットも非常に簡単なものになるのです。

この結果、削除不可能だが実行できることに制限がないという、パーシャルメソッドの第2のカテゴリが生まれることになる。2つのカテゴリを区別するための、基本的なルールが2つある。

  • パーシャルが明示的な修飾子(public、privateなど)を伴う場合、必ず実装しなければならないが、返り値はvoid、パラメータはout以外という制限はない。
  • パーシャルに明示的な修飾子のない場合、削除が可能だが、返り値はvoid、パラメータはout以外という制限がある。

純粋に技術的な観点から見れば、この新しいカテゴリのパーシャルメソッドは、必ず実装しなければならないという点で、実際には抽象(abstract)メソッドである。しかし必ずしもvirtualではないことから、Microsoftは、abstractというキーワードの転用が混乱を招くと判断したのだ。

パーシャルプロパティ、パーシャルコンストラクタ、パーシャル演算子など他クラスのメンバについては、C# 10に向けて検討されている。ただしこれらは、ソースジェネレータの機能拡張に必須なものではないため、必要以上に複雑な機能(feature creep)の導入は望まれていないのが現状である。

この記事に星をつける

おすすめ度
スタイル

こんにちは

コメントするには InfoQアカウントの登録 または が必要です。InfoQ に登録するとさまざまなことができます。

アカウント登録をしてInfoQをお楽しみください。

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

コミュニティコメント

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

HTML: a,b,br,blockquote,i,li,pre,u,ul,p

BT