余談: ジェネリック型に対する型パターン
Ver. 7.1
C# 7.0の時点では、ジェネリクスが絡む場合、
例えば以下のようなコードはコンパイル エラーになっていました。
(ジェネリックな型T
の変数に対してswitch
できない。ちなみに、一度object
にキャストすればできる。)
static void M<T>(T x)
{
switch (x)
{
case int i:
break;
case string s:
break;
}
}
「T
をint
やstring
として処理できない」と言った旨のコンパイル エラーが出ます。
さらにいうと、以下のような需要が結構ありそうな場面でも、C# 7.0ではコンパイル エラーになりました。
class Base { }
class Derived1 : Base { }
class Derived2 : Base { }
class Derived3 : Base { }
// こういう、型制約付きのやつですら 7.0 ではダメだった
static void N<T>(T x)
where T : Base
{
switch (x)
{
case Derived1 d:
break;
case Derived2 d:
break;
case Derived3 d:
break;
}
}
C# 7.0でも、以下のように、as
演算子を使った場合にはちゃんとコンパイルできます。
型パターンは、内部的にはas
演算子に展開される機能で、as
演算子にできて型パターンにできないことがあるのは不自然です。
static void N<T>(T x)
where T : Base
{
{ var d = x as Derived1; if (d != null) { return; } }
{ var d = x as Derived2; if (d != null) { return; } }
{ var d = x as Derived3; if (d != null) { return; } }
}
そこで、C# 7.1では、上記コードのような、ジェネリックな型に対する型パターンを使えるようになりました。 (新機能というよりは、仕様漏れ・バグ修正の類です。)
余談: ジェネリック型に対する is null
Ver. 8.0
C# 8.0 から、 以下のコードがコンパイルできるようになりました。
static bool M<T>(T x) => x is null;
元々 x == null
であればコンパイルできていたのに、x is null
がコンパイルできないのは変だということで修正されました。
型引数 T
が非 null 値型の時には常に false になります。