なんでも拡張

拡張メソッドは便利な構文なわけですが、インスタンス メソッドしか拡張できないのが残念なところです。拡張プロパティとかも作りたいことがあるし、静的な拡張(静的メソッドも既存のクラスに対して追加したように見える構文)もほしかったりします。という、なんでも拡張できる構文の案。

今のところ、以下のような構文で検討中。

extension class クラス名 : 拡張したい型
{
    // ここにメンバーは、拡張したい型の拡張メソッド、拡張プロパティなどになる
}

C# Design Notes (タプル型関連 再び)

前回C# Design Notes for Apr 12-22, 2016に引き続き、タプル型関連。

  • 分解
    • (x, y) = tuple; みたいなのを、tuple.Deconstruct(out x, out y); みたいなメソッド呼び出しとして解釈したい
    • タプル型専用の特別な構文にしないために、インスタンス or 拡張メソッドを通したい
    • ちょっと前までGetValueって名前を検討してたけど、一般的過ぎてすでに使われてそうなので、Deconstructメソッドにする
    • 要素の値を返すのはout引数にする。タプル型を分解するのにタプル型を返すわけにもいかないので
  • switchステートメントでの変換
    • 既存のswitchだとintとかstringしか受け付けないので、intとかへの暗黙的型変換できる型は変換結果で解釈されてた
    • 破壊的変更にならないようにするために、暗黙的型変換を定義した型は、今後も変換結果で解釈する
    • なので、そういう型(例えばintへの暗黙的型変換を持ったConst型)は case Const(int i): みたいなcaseにマッチしない(case 0:とかにはマッチする)
    • あんまり起きない状況だし、破壊的変更を避ける方を優先
  • タプル型間の変換
    • 「要素数が一致していて、各要素が暗黙的型変換できるなら、タプル型間でも暗黙的型変換できる」ってルールにするっぽい
  • タプル風のインスタンス生成
    • 任意の型に対して、左辺から型が推論できるなら、new (x, y)みたいな書き方でインスタンス生成できるようにする

最後の「タプル風インスタンス生成」はちょっと補足。

元々の発想は、「分解の構文をDeconstructメソッドを通すことで汎用化したんだし、構築の構文も汎用化すべき」というもの。タプル構築と、コンストラクター呼び出しを紐づけたいということになります。

が、例えば、その発想で行くと、以下のように、なんか直観にそぐわない「タプル型リテラルからの構築」ができてしまう。

Dictionary<int, string> d = (16, EqualityComparer<int>.Default); // さすがにこれは気持ち悪い

代わりと言ってはなんだけど、以下のような、newの後ろの型の省略を認めようという感じになってるみたい。

Point p = new (3, 4); // new Point(3, 4) と同じ
List<string> l1 = new (10); // 引数0個 or 1個でも大丈夫
List<int> l2 = new () { 3, 4, 5 }; // コレクション初期化子との併用もできるけど、() は省略できない

要するに、結局、左辺からの型推論みたいな構文を追加することになりそう。