Visual Studio 16.1.4Visual Studio 16.2 Preview 3が出たみたいです。

見た感じ、大半が不具合の修正っぽい雰囲気。

C# 的には、16.2.P3 マイルストーンの履歴的に、そろそろ null 許容参照型の作業が本格化していそうで、「C# によるプログラミング入門」の対応作業もそろそろやらなきゃ… と身構えていたんですが。 実際に 16.2 Preview 3 を触ってみると、あんまり入ってなさげ。Preview 4 に繰り越されたみたいです。

唯一、動作確認が取れたのが以下の機能。notnull 制約。

using System;
 
class C<T>
    where T : notnull
{
    public T Value { get; }
 
    public C(T value) => Value = value;
}
 
public class Program
{
    static void Main()
    {
        var c = new C<string>("");
        Console.WriteLine(c.Value.Length);
 
        var c1 = new C<int>(1);
        var c2 = new C<int?>(1); // 警告あり
        var c3 = new C<string?>(""); // 警告あり
        var c4 = new C<string>(null); // 警告あり
    }
}

これも、Preview 3 で対応するつもりがそんなになかったのか、 コンパイルはできるものの Visual Studio 上は未対応(コード補完もハイライトも効かない)な状態です。 (一方で、特にコンパイル エラーになったりはしない。)

notnull 制約

そういえば、この notnull 制約の話はあんまりこのブログで取り上げていなかったはず。 null 許容参照型周りはちょっと目を離すと結構実装が変わっているんで…

見たまんま、「この型引数は null を認めない」の意味です。 intstring は受け付けるけども、int?string? は受け付けない(警告のみですが)という型制約になります。 null 許容値型とnull 許容参照型を統一的に扱いたいがための仕様。

ただ、以下のようなコードは今のところ受け付けません。 notnull とは… (仕組み上しょうがなさそう。これを受け付けるためには .NET ランタイム側での対応が必要そうで結構な手間。)

class C<T>
    where T : notnull
{
    // せっかく notnull にしても、T? とは書けない。
    // [return: MaybeNull] という属性ベースの回避策を取る予定。
    public T? X() => default;
}

元々は、where T : object (object? がついてないんだから非 null 扱い)でいいんじゃないかって言われてたんですが、「object だと参照型っぽくて値型に使えなさそうな印象がある」という理由で新規キーワード追加になりました。

さらに言うと当初予定 では nonnull だったのが、今回の実装だと notnull (non と not の差)になっていたり。

C# ってあんまりこういう、2単語(not null)をつないだキーワードを採用することが少ないので、ちょっと最終的にもこのまま進むのかわからなかったりはします。荒れそう…