C# のパターンとパターン変数による is と case の拡張

C# のパターンとパターン変数の解説ビデオ

パターンを使った is 演算子と case ラベルの拡張について、簡単なデモのビデオを作りました。 こちらで概要はわかると思います。

ここでは C# 7.0 で導入された パターンパターン変数による is と case の拡張について説明します。

パターンというと正規表現を思い出す人が多いと思いますが、その形式のパターンではありません。もっと単純です。

C# の is 演算子におけるパターン

is はもともと、あるオブジェクトが特定の型かどうかチェックして、その型であれば true 異なれば false を返しました。

C# の「パターン」は三つあります。「定数」「特定の型指定」「var パターン」 の三つです。

具体例でみてみましょう。

using System;

class TestApp
{
  public static void Main(string[] args)
  {
    var i = 123;
    MyPrint(i);
  }

  public static void MyPrint(object o)
  {
    if (o is null)
    {
      Console.WriteLine("null");
    }
    else if (o is int i)
    {
      Console.WriteLine($"int {i}");
    }
    else
    {
      Console.WriteLine(o.ToString());
    }
  }
}

まず、o is null の箇所は、is を使って定数値 (この場合 null) とマッチするか評価しています。

この場合、o が null の場合、true となります。

次に o is int i の箇所は「特定の型指定」のパターンです。C# ではここで、パターン変数と呼ばれる変数を宣言することができ、 指定した型と互換性がある場合は、パターン変数にその値が入ります。

上のコードの場合は、MyPrint メソッドを呼び出すときに、123 という整数値が渡されていますから、式は true を返し、かつ i には 123 がセットされます。

次に「var パターン」です。var の場合、式は常に true を返し、常にパターン変数に値がセットされます。null でもセットされます。

使用例は次のコードをみてください。

static void Main()
{
  if (OpenFile(@"foo.txt") is var f && f == null)
  {
    Console.WriteLine("Unable to open a file.");
  }
  else
  {
    // f を使える
    Console.WriteLine($"The file is available. {f}");
  }
}

// ダミーのファイルを開く関数
static object OpenFile(string path)
{
  return null;
}

ダミーのファイルを開くための関数 OpenFile があって、その戻り値を利用するとします。

特に C 言語などではインラインで代入を行い、その結果を評価するということがしばしば行われます。C# に今回導入された var パターンで使えるパターン変数を使えば、 上記のように代入と値の評価を分けて記述することができるようになります。

C# の case ラベルでのパターン

swith 文の case ラベルでパターンを使うことができます。

次の例をみてください。Print メソッドに Employee オブジェクトを渡しています。

using System;

class Employee
{
  public string Name { get; set; }
  public int Age { get; set; }
  public string Title { get; set; }
}

class TestApp
{
  public static void Main(string[] args)
  {
    var emp1 = new Employee
    {
      Name = "Hanako",
      Age = 24,
      Title = "HR"
    };

    Print(emp1);
  }

  public static void Print(object o)
  {
    switch (o)
    {
      case Employee p:
        Console.WriteLine($"{p.Name} {p.Title} {p.Age}");
        break;
      default:
        Console.WriteLine("Unknown");
        break;
    }
  }
}

28行目の Print メソッド内の switch の最初の case ラベルで、Employee p としています。 ここがパターン変数になっています。評価した変数 o が Employee 型である場合、p に o が Employee オブジェクトにキャストされてセットされます。

さらに case にて when フィルターを記述できます

  public static void Print(object o)
  {
    switch (o)
    {
      case Employee p when p.Age < 20:
        Console.WriteLine("Internship");
        break;
      case Employee p:
        Console.WriteLine($"{p.Name} {p.Title} {p.Age}");
        break;
      default:
        Console.WriteLine("default");
        break;
    }
  }

when は C# 6.0 で例外フィルターとして導入されましたが、C# 7.0 ではパターンのフィルターとしても使えるようになりました。

上記の5行目では、変数 o が Employee 型であり、かつ、Age プロパティが返す値が 20 より小さい場合に、最初の case がマッチします。

以上、C# のパターンとパターン変数による is と case の拡張について説明しました。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 C# 入門