一昨日のの補足。

先日は以下のようなLanguage Design Notesが出てたわけですが。

コンストラクター引数とプロパティの名前の一致を見て、何番目の引数がどのプロパティに対応するかを調べる(position-to-propertyマッチする)方針を使おうという話。 もちろんいろんな対案あった中で、今、こういう方針に傾いてるという話なんですが、そういう過程抜きに「名前の一致を見る」の話だけしたので多少炎上中。

ということで、対案の1つ、タプルを使ったパターンの話も公開されました。

以下のようなメソッドを用意することで、position-to-propertyマッチしようというもの。 拡張メソッドでもいいことにしておけば、既存のクラスの拡張もできます(ただし、その拡張メソッドを書くのは手動。大変めんどいはず)。

public class Person
{
  ...
  public (string FirstName, string LastName) GetValues() { ... }
  public Person With((string FirstName, string LastName) builder) { ... }
}

with式みたいなものの実現には、既存の言語構文だけでやるならいわゆる「ビルダー パターン」を使ったりします。 そのためにはビルダー用のクラスを1個余計に作らないと行けなくて、余計なメモリ アロケーションが発生したり、余計なクラスを書く手間が掛かったり。

でも、タプル型を使えば、タプルはmutableな構造体なので余計なアロケーションは起きない。 それに、新しいクラスの追加も必要なくて、手間は多少マシになる。 タプルは元々、引数位置と名前の対応関係を持っているので、黒魔術的な特殊処理なしでposition-to-propertyマッチできるはず、ということになります。

とはいえ、以下のように、悪い面もあります。

  • 既存の型に対してそのままでは使えない。GetValuesWithなどの追加(拡張メソッドでもいいけど、手動での追加)が必要
  • オブジェクトの分解(GetValues)やwith式(With)はインスタンス メソッドになるのでvirtualにできても、新規インスタンス作成ではできない
  • (レコード型などの新構文で)コンパイラーが自動生成するコードが増える
  • タプル型という、別の新構文に強く依存することになる(複雑度が増す)

というような話があっての、先日の「名前で解決」の流れになったという話です。