拡張メンバー

Design Meetingで拡張メンバーの検討をしてたみたい。 (拡張メンバー = 初期検討段階で「extension everything」(なんでも拡張)って言ってたやつ。拡張メソッド以外に、プロパティとかも拡張できるようにする構文)

現状、以下のような感じ。

  • extension classってキーワードで、通常のクラスを継承したような構文で作る
    • 定義したメンバーは拡張メソッド同様、静的メソッド化される
    • プロパティは、「インデックス付きプロパティ」(ILレベルとかVBにはある。C#のレベルで使ってないだけ)に展開するのがよさそうだけど、現状のC#では認めてないものなのでちょっと悩ましい
  • インスタンス メンバー風の拡張だけじゃなくて、静的メソッドの拡張も足せる
  • コンストラクターも足せる
  • 演算子をどうするかは悩ましい
    • 四則演算とかはいいと思うんだけど
    • == とかが怪しい
  • Personクラスの拡張Enrolleeがあったとして、Personの通常のインスタンス メンバーと、拡張の方のメンバーを呼び分ける構文がほしい
    • 優先されるのは通常のインスタンス メンバー
    • たぶん((Emrollee)person).Supervisorみたいなキャスト構文でやる

コンパイラー組み込み

「時々C#にもインライン アセンブラーがほしい」問題に対して、 別解法の提案。

C#では書けないもの

まず、「ILを使えば書けるけど、C#では書けない」みたいなのの例。

  • CLRがやってるみたいなネイティブ コードとの相互運用をビルド時に静的に作ってしまおうと思うと、いくつかC#では書けない命令が必要
  • infoof(information ofの略。typeofと同じノリでMethodInfoとかを取る)相当の機能をライブラリでやろうと思うとldtoken命令が必要
  • スライスを作るのにC#では書けない機能が必要

インライン アセンブラーはやらない

  • 時々しかない要件のためにILインライン アセンブラーを実装するのはコストに見合わない
  • というか、混ぜるのよくない。C#コンパイラーとILアセンブラーは別ツールとして、別チームが個別開発すべき

別解法の提案

で、提案してるのが「コンパイラー組み込み」(compiler intrinsics: コンパイラーが内在して持ってる実装)。

いくつかのC++コンパイラーは、プログラマーがSSE命令とかAVX命令みたいな特殊な命令を使えるように、コンパイラー組み込みの特殊なメソッドを提供してたりします。 C#でもそういう特殊なメソッドを用意して、上記のような通常のC#では書けない場面に対処すればいいんじゃないかという提案を出してきています。

文法的にはexternメソッドを使うだけ。CompilerIntrinsic属性を付けることで、ネイティブDLL中のネイティブ メソッドを呼ぶ代わりに、コンパイラーが直接その場所にIL命令を出力するというもの。 これなら今から新文法について考える必要もないし、簡単に目的が達成できそう。

bool型やenum型のswitchの完備性

bool型にはtruefalseしかないはずなんだから、以下のdefault句は不要にできないかという話。ご意見求む状態。

bool b = ...;
switch (b)
{
    case true:
    case false:
        break;
    default:
        break; // warning: unreachable code?
}

これ、昔から要望としては頻出なんですが、できない理由もあります。ILは結構低級機能を提供しているので、bool型の変数を無理やり書き換えて、trueでもfalseでもない値を作れて、上記default句に来ちゃう場合があったり。 というか、C#でも、以下のような書き方でそういう値を作れます。

それに、後方互換性を考えると、既存のswitchには警告も出せないです。

という背景の中、今後導入予定のmatch式(switchの式バージョン)ではこういう普通はあり得ないdefault句に対する警告がほしいですか?という質問。

言語サポート付きのobsolete

今、obsolete (廃止したい、もう使ってほしくない)なメンバーにはObsolete属性を付けて対処しています。 でも、この属性ベースのやり方じゃなくて、C#の言語機能としてobsoleteキーワードが必要かもという話が。

シナリオ的には以下のようなもの。

// シナリオ 1:
int f(string s);                 // ライブラリv1がこいつを持ってる
int f(string s, bool b = false); // v2でこれに変えたい
// バイナリ互換性のためにf(string)は消せない
// でも、今後、オーバーロード解決時に、f("") で優先的に f(string, bool) の方を見てほしい(今は無理)

// シナリオ 2:
float g();  // ライブラリv1がこいつを持ってる
double g(); // v2でこれに変えたい
// バイナリ互換性のためにfloat g()は消せない
// でも、今後、double g()を使いたい(呼び分けどころか今はそもそも定義すら不可能)

これに対して、v1側にobsolete修飾子を付けることで、v2側の新メソッドの追加・オーバーロード解決できるようにしたいとのこと。

TryRoslyn

Roslynリポジトリの各ブランチの最新版でのコンパイルを、オンラインで試して見れるサイト作ってる人がいた。

C#チームの公式提供じゃないし、まだまだ作業途中みたいですけども。

  • Lucian (C#チームの中の人)が、自分のリポジトリでasync任意戻り値の試験実装してる
  • ashmind (TryRoslyn作ってる人)が、そのLucianの個人リポジトリのブランチをTryRoslynに追加してくれた
  • Lucian、早速利用

みたいな感じになってた。