[C#] switchパターンマッチングの基本的な使い方

C#のswitchパターンマッチングは、switch文を拡張して、型や条件に基づいてより柔軟に分岐処理を行う機能です。

基本的な使い方として、switch文の中でcaseラベルにパターンを指定し、対象のオブジェクトがそのパターンに一致するかどうかを評価します。

例えば、型パターンを使用してオブジェクトの型をチェックしたり、プロパティパターンを用いてオブジェクトのプロパティの値を評価することができます。

これにより、複雑な条件分岐を簡潔に記述でき、コードの可読性が向上します。

この記事でわかること
  • switchパターンマッチングの基本的な構文とその利点
  • 型パターン、プロパティパターン、タプルパターンの具体的な使用方法
  • 複雑な条件分岐を簡略化するための応用例
  • データ型の安全なキャストを実現する方法
  • パターンマッチングによるコードの可読性向上の効果

目次から探す

switchパターンマッチングとは

パターンマッチングの概要

パターンマッチングは、データの構造や型に基づいて処理を分岐させる手法です。

C#では、特定の条件に基づいてオブジェクトの型やプロパティを確認し、それに応じた処理を行うことができます。

これにより、コードの可読性が向上し、複雑な条件分岐を簡潔に記述することが可能です。

C#におけるswitch文の進化

C#のswitch文は、もともと整数や文字列などの単純な型に対する条件分岐を行うために使用されていました。

しかし、C# 7.0以降、switch文はパターンマッチングをサポートするようになり、より柔軟で強力な条件分岐が可能になりました。

これにより、switch文は単なる値の比較だけでなく、オブジェクトの型やプロパティに基づく条件分岐も行えるようになりました。

パターンマッチングの利点

パターンマッチングを使用することで、以下のような利点があります。

スクロールできます
利点説明
可読性の向上複雑な条件分岐を簡潔に記述でき、コードの可読性が向上します。
型安全性型に基づく条件分岐を行うため、型安全性が向上します。
柔軟性オブジェクトのプロパティや型に基づく柔軟な条件分岐が可能です。

これらの利点により、パターンマッチングはC#プログラミングにおいて非常に有用な機能となっています。

特に、複雑なデータ構造を扱う際に、その真価を発揮します。

基本的な使い方

型パターンの使用方法

型パターンは、オブジェクトの型を確認し、その型に応じた処理を行うためのパターンです。

以下に型パターンの基本的な使用方法を示します。

using System;
class Program
{
    static void Main()
    {
        object obj = "こんにちは"; // オブジェクトに文字列を代入
        switch (obj)
        {
            case string s:
                Console.WriteLine($"文字列です: {s}"); // 文字列の場合の処理
                break;
            case int i:
                Console.WriteLine($"整数です: {i}"); // 整数の場合の処理
                break;
            default:
                Console.WriteLine("未知の型です"); // その他の型の場合の処理
                break;
        }
    }
}
文字列です: こんにちは

この例では、objが文字列であるため、case string s:のブロックが実行されます。

型パターンを使用することで、オブジェクトの型に応じた処理を簡潔に記述できます。

プロパティパターンの活用

プロパティパターンは、オブジェクトのプロパティの値を確認し、その値に応じた処理を行うためのパターンです。

以下にプロパティパターンの例を示します。

using System;
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
class Program
{
    static void Main()
    {
        var person = new Person { Name = "太郎", Age = 30 }; // Personオブジェクトを作成
        switch (person)
        {
            case { Name: "太郎", Age: 30 }:
                Console.WriteLine("太郎さん、30歳です"); // 特定のプロパティ値の場合の処理
                break;
            case { Age: var age } when age > 20:
                Console.WriteLine($"20歳以上です: {age}歳"); // 年齢が20歳以上の場合の処理
                break;
            default:
                Console.WriteLine("条件に一致しません"); // その他の場合の処理
                break;
        }
    }
}
太郎さん、30歳です

この例では、personのプロパティNameAgeが特定の値に一致する場合に対応する処理が実行されます。

プロパティパターンを使用することで、オブジェクトの詳細な状態に基づく条件分岐が可能です。

タプルパターンの利用

タプルパターンは、複数の値を持つタプルに対してパターンマッチングを行うためのパターンです。

以下にタプルパターンの例を示します。

using System;
class Program
{
    static void Main()
    {
        var point = (X: 3, Y: 4); // タプルを作成
        switch (point)
        {
            case (0, 0):
                Console.WriteLine("原点です"); // 原点の場合の処理
                break;
            case (var x, var y) when x == y:
                Console.WriteLine($"XとYが等しい: {x}, {y}"); // XとYが等しい場合の処理
                break;
            default:
                Console.WriteLine($"座標: {point.X}, {point.Y}"); // その他の場合の処理
                break;
        }
    }
}
座標: 3, 4

この例では、pointの座標が特定の条件に一致する場合に対応する処理が実行されます。

タプルパターンを使用することで、複数の値に基づく条件分岐が簡潔に記述できます。

論理パターンの組み合わせ

論理パターンは、複数のパターンを論理的に組み合わせて条件分岐を行うためのパターンです。

以下に論理パターンの例を示します。

using System;
class Program
{
    static void Main()
    {
        object obj = 42; // オブジェクトに整数を代入
        switch (obj)
        {
            case int i and > 0:
                Console.WriteLine($"正の整数です: {i}"); // 正の整数の場合の処理
                break;
            case int i and < 0:
                Console.WriteLine($"負の整数です: {i}"); // 負の整数の場合の処理
                break;
            case not int:
                Console.WriteLine("整数ではありません"); // 整数以外の場合の処理
                break;
        }
    }
}
正の整数です: 42

この例では、objが正の整数であるため、case int i and > 0:のブロックが実行されます。

論理パターンを使用することで、複数の条件を組み合わせた柔軟な条件分岐が可能です。

型パターンの詳細

型パターンの基本構文

型パターンは、オブジェクトの型を確認し、その型に応じた処理を行うための構文です。

基本的な構文は以下の通りです。

switch (変数)
{
    case 型名 変数名:
        // 型が一致した場合の処理
        break;
    default:
        // その他の場合の処理
        break;
}

この構文では、switch文の中でcaseキーワードを使用し、特定の型にマッチするかどうかを確認します。

型が一致した場合、その型にキャストされた変数を使用して処理を行います。

型パターンの実例

型パターンを使用することで、異なる型のオブジェクトに対して異なる処理を行うことができます。

以下に型パターンの実例を示します。

using System;
class Program
{
    static void Main()
    {
        object[] items = { "文字列", 123, 45.67, true }; // 異なる型のオブジェクトを含む配列
        foreach (var item in items)
        {
            switch (item)
            {
                case string s:
                    Console.WriteLine($"文字列: {s}"); // 文字列の場合の処理
                    break;
                case int i:
                    Console.WriteLine($"整数: {i}"); // 整数の場合の処理
                    break;
                case double d:
                    Console.WriteLine($"小数: {d}"); // 小数の場合の処理
                    break;
                default:
                    Console.WriteLine("その他の型"); // その他の型の場合の処理
                    break;
            }
        }
    }
}
文字列: 文字列
整数: 123
小数: 45.67
その他の型

この例では、items配列の各要素に対して型パターンを使用し、型に応じた処理を行っています。

型パターンを使用することで、異なる型のオブジェクトを簡潔に処理できます。

型パターンの注意点

型パターンを使用する際には、いくつかの注意点があります。

  • 型の一致: 型パターンは、指定された型と完全に一致する場合にのみマッチします。

例えば、int型の変数に対してcase doubleはマッチしません。

  • 順序: switch文のcaseブロックは上から順に評価されるため、より具体的な型を先に記述する必要があります。

一般的な型を先に記述すると、特定の型にマッチする前に処理されてしまう可能性があります。

  • nullの扱い: nullは特定の型にマッチしないため、case nullを使用してnull値を処理する必要があります。

これらの注意点を考慮することで、型パターンを効果的に活用することができます。

プロパティパターンの詳細

プロパティパターンの基本構文

プロパティパターンは、オブジェクトのプロパティの値を確認し、その値に基づいて処理を行うための構文です。

基本的な構文は以下の通りです。

switch (変数)
{
    case { プロパティ名: 値 }:
        // プロパティが特定の値に一致した場合の処理
        break;
    default:
        // その他の場合の処理
        break;
}

この構文では、switch文の中でcaseキーワードを使用し、オブジェクトの特定のプロパティが指定された値に一致するかどうかを確認します。

プロパティパターンの実例

プロパティパターンを使用することで、オブジェクトの詳細な状態に基づく条件分岐が可能です。

以下にプロパティパターンの実例を示します。

using System;
class Car
{
    public string Make { get; set; }
    public string Model { get; set; }
    public int Year { get; set; }
}
class Program
{
    static void Main()
    {
        var car = new Car { Make = "Toyota", Model = "Corolla", Year = 2020 }; // Carオブジェクトを作成
        switch (car)
        {
            case { Make: "Toyota", Model: "Corolla" }:
                Console.WriteLine("トヨタのカローラです"); // 特定のメーカーとモデルの場合の処理
                break;
            case { Year: var year } when year < 2000:
                Console.WriteLine($"古い車です: {year}年"); // 年式が2000年未満の場合の処理
                break;
            default:
                Console.WriteLine("条件に一致しません"); // その他の場合の処理
                break;
        }
    }
}
トヨタのカローラです

この例では、carオブジェクトのMakeModelプロパティが特定の値に一致する場合に対応する処理が実行されます。

プロパティパターンを使用することで、オブジェクトのプロパティに基づく詳細な条件分岐が可能です。

プロパティパターンの注意点

プロパティパターンを使用する際には、いくつかの注意点があります。

  • プロパティの存在: プロパティパターンを使用する場合、指定するプロパティがオブジェクトに存在する必要があります。

存在しないプロパティを指定するとコンパイルエラーになります。

  • nullの扱い: オブジェクトがnullの場合、プロパティパターンはマッチしません。

nullを処理する場合は、case nullを使用する必要があります。

  • 条件の順序: switch文のcaseブロックは上から順に評価されるため、より具体的な条件を先に記述する必要があります。

一般的な条件を先に記述すると、特定の条件にマッチする前に処理されてしまう可能性があります。

これらの注意点を考慮することで、プロパティパターンを効果的に活用することができます。

タプルパターンの詳細

タプルパターンの基本構文

タプルパターンは、複数の値を持つタプルに対してパターンマッチングを行うための構文です。

基本的な構文は以下の通りです。

switch (タプル)
{
    case (値1, 値2, ...):
        // タプルの各要素が特定の値に一致した場合の処理
        break;
    default:
        // その他の場合の処理
        break;
}

この構文では、switch文の中でcaseキーワードを使用し、タプルの各要素が指定された値に一致するかどうかを確認します。

タプルパターンの実例

タプルパターンを使用することで、複数の値に基づく条件分岐が簡潔に記述できます。

以下にタプルパターンの実例を示します。

using System;
class Program
{
    static void Main()
    {
        var point = (X: 1, Y: 2); // タプルを作成
        switch (point)
        {
            case (0, 0):
                Console.WriteLine("原点です"); // 原点の場合の処理
                break;
            case (1, 2):
                Console.WriteLine("座標は (1, 2) です"); // 特定の座標の場合の処理
                break;
            case (var x, var y) when x == y:
                Console.WriteLine($"XとYが等しい: {x}, {y}"); // XとYが等しい場合の処理
                break;
            default:
                Console.WriteLine($"座標: {point.X}, {point.Y}"); // その他の場合の処理
                break;
        }
    }
}
座標は (1, 2) です

この例では、pointの座標が特定の条件に一致する場合に対応する処理が実行されます。

タプルパターンを使用することで、複数の値に基づく条件分岐を簡潔に記述できます。

タプルパターンの注意点

タプルパターンを使用する際には、いくつかの注意点があります。

  • 要素の数と順序: タプルパターンは、タプルの要素の数と順序が一致する場合にのみマッチします。

要素の数や順序が異なる場合はマッチしません。

  • 型の一致: 各要素の型も一致する必要があります。

異なる型の要素に対してはマッチしません。

  • 条件の順序: switch文のcaseブロックは上から順に評価されるため、より具体的な条件を先に記述する必要があります。

一般的な条件を先に記述すると、特定の条件にマッチする前に処理されてしまう可能性があります。

これらの注意点を考慮することで、タプルパターンを効果的に活用することができます。

switchパターンマッチングの応用例

複雑な条件分岐の簡略化

switchパターンマッチングを使用することで、複雑な条件分岐を簡潔に記述することができます。

従来のif-else文を使用した場合、条件が増えるにつれてコードが冗長になりがちですが、switchパターンマッチングを用いることで、条件を整理しやすくなります。

using System;
class Program
{
    static void Main()
    {
        object[] items = { "Hello", 42, 3.14, null, new DateTime(2023, 1, 1) }; // 異なる型のオブジェクトを含む配列
        foreach (var item in items)
        {
            switch (item)
            {
                case string s when s.Length > 5:
                    Console.WriteLine($"長い文字列: {s}"); // 文字列が5文字以上の場合の処理
                    break;
                case int i when i > 0:
                    Console.WriteLine($"正の整数: {i}"); // 正の整数の場合の処理
                    break;
                case double d:
                    Console.WriteLine($"小数: {d}"); // 小数の場合の処理
                    break;
                case null:
                    Console.WriteLine("null値です"); // nullの場合の処理
                    break;
                default:
                    Console.WriteLine("その他の型"); // その他の型の場合の処理
                    break;
            }
        }
    }
}
その他の型
正の整数: 42
小数: 3.14
null値です
その他の型

この例では、異なる型のオブジェクトに対して複数の条件を組み合わせて処理を行っています。

switchパターンマッチングを使用することで、条件分岐が明確になり、コードの可読性が向上します。

データ型の安全なキャスト

switchパターンマッチングを使用することで、データ型の安全なキャストが可能になります。

従来のキャスト操作では、型が一致しない場合に例外が発生する可能性がありますが、パターンマッチングを使用することで、型が一致する場合のみキャストを行うことができます。

using System;
class Program
{
    static void Main()
    {
        object obj = "123"; // 文字列としての数値
        switch (obj)
        {
            case string s when int.TryParse(s, out int result):
                Console.WriteLine($"整数に変換成功: {result}"); // 文字列を整数に変換できた場合の処理
                break;
            case int i:
                Console.WriteLine($"整数: {i}"); // 既に整数の場合の処理
                break;
            default:
                Console.WriteLine("変換できません"); // その他の場合の処理
                break;
        }
    }
}
整数に変換成功: 123

この例では、文字列が整数に変換可能な場合にのみキャストを行っています。

switchパターンマッチングを使用することで、型の安全性を確保しつつ、柔軟なキャスト操作が可能です。

パターンマッチングによるコードの可読性向上

パターンマッチングを使用することで、コードの可読性が大幅に向上します。

特に、複数の条件を組み合わせた場合や、オブジェクトのプロパティに基づく条件分岐を行う場合に、その効果が顕著です。

using System;
class Employee
{
    public string Name { get; set; }
    public string Position { get; set; }
    public int Experience { get; set; }
}
class Program
{
    static void Main()
    {
        var employee = new Employee { Name = "山田", Position = "Manager", Experience = 5 }; // Employeeオブジェクトを作成
        switch (employee)
        {
            case { Position: "Manager", Experience: >= 5 }:
                Console.WriteLine("経験豊富なマネージャーです"); // 特定のポジションと経験年数の場合の処理
                break;
            case { Position: "Developer", Experience: < 3 }:
                Console.WriteLine("若手の開発者です"); // 若手の開発者の場合の処理
                break;
            default:
                Console.WriteLine("その他の従業員"); // その他の場合の処理
                break;
        }
    }
}
経験豊富なマネージャーです

この例では、employeeオブジェクトのプロパティに基づいて条件分岐を行っています。

パターンマッチングを使用することで、条件が明確に記述され、コードの可読性が向上します。

よくある質問

switchパターンマッチングはどのバージョンから利用可能ですか?

switchパターンマッチングは、C# 7.0から利用可能になりました。

このバージョンでは、型パターンや定数パターンが導入され、C# 8.0以降ではプロパティパターンやタプルパターン、論理パターンなどが追加され、機能が拡張されています。

したがって、これらの機能を使用するには、C# 7.0以上のバージョンが必要です。

switchパターンマッチングとif文の違いは何ですか?

switchパターンマッチングとif文は、どちらも条件分岐を行うための構文ですが、いくつかの違いがあります。

  • 構文の簡潔さ: switchパターンマッチングは、複数の条件を一度に評価する際に、より簡潔に記述できます。

特に、複数の型やプロパティに基づく条件分岐を行う場合に有効です。

  • 可読性: switchパターンマッチングは、条件が明確に整理されているため、可読性が向上します。

特に、複雑な条件分岐を行う場合に、コードの見通しが良くなります。

  • 用途: if文は、より柔軟で細かい条件分岐が可能ですが、switchパターンマッチングは、特定の型や値に基づく条件分岐に特化しています。

パターンマッチングを使う際のパフォーマンスへの影響はありますか?

パターンマッチングを使用する際のパフォーマンスへの影響は、通常は最小限です。

C#コンパイラは、パターンマッチングを効率的に処理するように最適化されています。

ただし、非常に多くの条件を持つ複雑なパターンマッチングを行う場合や、頻繁に実行されるコードで使用する場合は、パフォーマンスに注意を払う必要があります。

一般的には、パフォーマンスよりもコードの可読性や保守性を優先することが推奨されます。

まとめ

この記事では、C#におけるswitchパターンマッチングの基本的な使い方から応用例までを詳しく解説しました。

switchパターンマッチングを活用することで、複雑な条件分岐を簡潔に記述し、コードの可読性と保守性を向上させることが可能です。

これを機に、実際のプロジェクトでswitchパターンマッチングを試し、コードの効率化を図ってみてはいかがでしょうか。

当サイトはリンクフリーです。出典元を明記していただければ、ご自由に引用していただいて構いません。

関連カテゴリーから探す

  • 条件分岐 (10)
  • 繰り返し文 (10)
  • URLをコピーしました!
目次から探す