LoginSignup
26
21

More than 5 years have passed since last update.

型パターン(C#7)

Last updated at Posted at 2019-01-06

C#7時代の型変換

C#7.0から、型変換において、型スイッチ 型パターンという便利な書き方ができるようになりました。

コメントで型スイッチは古い呼び方と教えていただきました!

pattern-matching
https://docs.microsoft.com/ja-jp/dotnet/csharp/pattern-matching

こちらの記事様を参考にさせていただきました。

is、switch の拡張 (型スイッチ) - C# によるプログラミング
https://ufcpp.net/study/csharp/datatype/typeswitch/

この記事では簡単な使用例を示します。

is/as演算子

そのまえに、is/as演算子を使った従来の型変換について超簡単におさらい。

is演算子

変数名で指定したクラスにダウンキャスト可能かどうかを調べる。
ダウンキャストできるか否かが、true/falseで返される。

構文 : 変数名 is クラス名

Object obj = "hoge";
String str = (String)obj;
Console.WriteLine(obj is str); // true      

as演算子

is演算子のように前もって診断しなくても安全にダウンキャストできる。ダウンキャストを実行して、ダウンキャスト不可の場合はnullを返す。

構文 : 変数名 as クラス名

Object obj = "hoge";
String str = obj as String;
Console.WriteLine(str == null); // false        

使い分け

もし、ダウンキャスト判定するだけなら、is演算子だけで十分です。

Object obj = "hoge";
if (obj is string) Console.WriteLine("Do something!");

ただし、判定した上で、さらにダウンキャストもしたい場合。is演算子を使うと以下のような二重処理のコードになってしまい、なんかあんまり良くない感じです。

Object obj = "hoge";
// 処理[1]->判定
if (obj is string) {
  // 処理[2]->キャスト
  var s = (string)obj;
}

この場合、as演算子を使った方がスマートです。

Object obj = "hoge";
var s = obj as string;
if (s != null) Console.WriteLine("Do something!");

型スイッチ 型パターン (C#7.0)

やっと本題です。

C#7では、上記のis演算子が拡張され「ダウンキャストできるかどうかの判定」と「新しい変数の定義」が同時にできるようになりました。これを型スイッチ 型パターンといい、さらにスマートな記述ができるようになりました。

ダウンキャスト可能ならtrueが返り、ダウンキャストが実行され変数が定義されます。

構文 : 変数 is 型 変数名

Object obj = "hoge";
if (obj is string str) Console.WriteLine("Do something!");

switch文の拡張 (C#7.0)

型スイッチはswitch文でも使えます。
caseの後ろにも書けるようになりました。

構文 : case 型 変数名:

Object obj = "hoge";
switch (obj) {
  case int x:
    Console.WriteLine(x);
    break;
  case string str: // <- このcaseにマッチする
    Console.WriteLine(str); // hoge
    break;
}

whenキーワード

また、whenによる条件フィルターをかけることもできます。

構文 : case 型 変数名 when 条件式

Object obj = "hoge";
switch (obj) {
  case int x:
    Console.WriteLine(x);
    break;
  case string str when (str.Length == 4):
    Console.WriteLine(str); // hoge
    break;
}

ジェネリックな型スイッチ (C#7.1)

さらにC#は進化を止めず、C#7.1では、ジェネリック型の型スイッチが使えるようになりました。つまり、ジェネリック型の引数に対してパターンマッチングすることができます。かなり便利な機能だと思うのですが、C#7.0まではこれをやるとコンパイルエラーとなります。

switch (x) {
  case int i:
    Console.WriteLine(i);
    break;
  case string s:
    Console.WriteLine(s);
    break;
  default:
    Console.WriteLine("not match");
    break;    
}
// C#7.0まではコンパイルエラー

おわり

26
21
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
21