Visual Studio 16.1 Preview 1

Visual Studio 16.1 Preview 1 が来てたことに今更気付くなど…

先日のVisual Studio 2019 GA の話で書いた通り、これまで「Visual Studio 2019 Preview」をインストールしていた人のところには 16.1 Preview 1 が配信されているはずです。 GA 版にかまけてしばらく Preview チャネルの方を見てなかった… (4/10 の配信)

Language Feature Statusによれば、16.0 から 16.1 Preview 1 での差分は以下の1点のみです。

ジェネリックな構造体でも条件さえ満たせばポインターとか stackalloc とか使えるようになりました。 C# によるプログラミング入門にも反映させてあります。

using の話とか非同期ストリームの話とか、先に埋めた方がいいだろと思うものもちらほらあったりはするんですが、なかなか手付かずに…

Design Notes

また一気に大量アップロード…

ちょっと一気に来過ぎて自分も大筋しか見れてないんですが… 興味の引かれたところだけ抜粋:

switch

  • switch 式の優先度変えたいって
    • 今: 比較演算子の辺り。< とかの近く
    • 変更後: 単項演算子の直後。インデクサー、キャスト、await とかよりは下で、掛け算の * とかよりは上。
  • やっぱ {} が暗黙的に「null ではない」の意味なの混乱しそう
    • でも、is での挙動と合わせないと変だし
  • 将来の or パターンのために、今、case X or みたいなのは警告出すべき?
    • 今もう動くコードなので、破壊的変更になっちゃうから無理そう

非同期ストリーム

  • 非同期イテレーターへの CancellationToken の渡し方どうしよう?
    • 引数に所定の属性を付けたら、生成されるイテレーターに伝搬するようにしたい

??= 演算の戻り値の型

以下のコードを書いたとき、 c の型はどうあるべきか

int? b = null;
var c = b ??= 5;
  • 今(16.1 Preview 1)の実装は int? になる
    • b ??= 5b = b ?? 5 が同じ意味になるように
  • 今後、int になるように変える

Index/Range

  • 先日書いた「パターン ベースにする」という話、確定
  • Length があればまずそれを、なければ Count を調べる
    • Length の戻り値が int でなければそれは無視して Count を調べる
    • Count の実装が O(1) じゃない場合の心配とかはしない(それは .NET のデザイン ガイドライン違反)
  • [Range r] なインデクサーよりも、Slice(int start, int length) の方が優先される
  • インスタンス メンバーしか追わない(拡張メソッドは調べない)
  • int 以外のインデクサーは認めない(暗黙の型変換とかは追わない)し、引数も1個だけのしか調べない
  • Sliceintが2引数のものしか調べない

null 解析(null 許容参照型)

  • 到達不能なコード(return の後ろとか)の null 解析はしない
  • 匿名型のメンバーの nullability は追うべき? → yes
  • 以下のコード、実装側で区別できなくて困らない?
interface I
{
    void Foo<T>(T value) where T : class;
    void Foo<T>(T? value) where T : struct;
}

→ 困る。実装側に where 制約を付けて区別できるようにしないといけない。

  • dynamic な変数の nullability は追う? → yes

インターフェイスのデフォルト実装

  • reabstraction は認めるか
    • abstract を付けて、デフォルト実装があるメソッドを再び「派生クラスでの実装が必須」の状態に戻す話
    • もし実装が楽そうならやるべき理由はある。実現性を要調査 → 十分できそう
  • デフォルト実装ないから object のメンバー、特に MemberwiseClone のアクセスを認めるか
    • たぶん yes。でも問題起こしそう。object の protected メンバーはアクセスできないようにするかも → できなくするほうがだいぶ好ましそう
  • クラス同様、partial メソッドは暗黙的に private? → yes

Better Obsoletion (Obsolete 属性をよりよくしたい)

C# 側ではなくて dotnet/designs の方に出ている話ですがもう1個。

.NET の基本ライブラリには、廃止予定にしてしまいたい(Obsolete 属性を付けてしまいたい) API がもう結構大量にあるわけですが。 今の Obsolete 属性の仕様だと「全部抑止」か「全部警告」の all or nothing で困るという話。

「ある特定の Obsolete 属性は無視して、それ以外の Obsolete 属性はちゃんと警告になる」みたいなグルーピング機能が欲しく、そのために Obsolete 属性に DiagnosticId プロパティを追加しようという提案になっています。

新しい属性を作ることも考えたけど、そしたら皮肉なことに Obsolete 属性自体に Obsolete 属性がついてしまうという問題。