なんかいろいろと書いてくブログ

関東のどこかで働く、一般人

【C#】Switch式(Switch Expression)のもろもろ

tags:[C#]

C# 8.0から使用できるSwitvh 式(Switch Expression)
Switch文(Switch Statement)とは明確に違っていてステートによるではなくパターンマッチングにを行う

正直、この辺読んでおけばこの記事を読む必要はない

Switch文からの置き換え

やりたいことはどちらもある条件を評価して条件分岐なので おきかえることができる 以下のようなSwitch文は

public static void SwitchStatment(TestEnum e)
{
    string consoleText;
    switch (e)
    {
        case TestEnum.Test1:
            consoleText = "Swirch Test1";
            break;
        case TestEnum.Test2:
            consoleText = "Swirch  Test2";
            break;
        case TestEnum.Test3:
            consoleText = "Swirch  Test2";
            break;
        default:
            consoleText = "Swirch  TestDefault";
            break;
    }
    Console.WriteLine(consoleText);
}
public enum TestEnum
{
    Test1,
    Test2,
    Test3,
}

Switch式だとこうなる Caseやbreakがなくなって、かなりすっきちとした書き方になった

public static void SwitchExpressionDemo(TestEnum e)
{
    string consoleText = e switch
    {
        TestEnum.Test1 => "Swirch Test1",
        TestEnum.Test2 => "Swirch  Test2",
        TestEnum.Test3 => "Swirch  Test2",
        _ => "Swirch  TestDefault",
    };
    Console.WriteLine(consoleText);
}
public enum TestEnum
{
    Test1,
    Test2,
    Test3,
}

ちなみに、VidualStudioのサジェストとして、Switch文 -> Switch式への変換を提案される (言語的にもこちらを使用してほしいのかもしれない)

learn.microsoft.com

Switch変換サジェスチョン

パターンマッチング

パターンマッチングとして提案されているSwitch式は (公式Docにもswitchキーワードを使ったパターン マッチング式と紹介されている)
以下のような下記かたもできる(これらはSwitch文でもできる)

public static void SwitchExpressionDemo2(int a)
{
    string consoleText = a switch
    {
        0 => "a は 0",
        > 0 => "a は0 未満",
        <= 0 => "a は0以下",
    };
    Console.WriteLine(consoleText);
}

また、ケース ガードが使用できるので whenを用いて柔軟に式の評価ができる

public static void SwitchExpressionDemo3(int a, int b)
{
    string consoleText = a switch
    {
        0 => "a は 0",
        > 0 when a >= b => "a は0 以上かつb以上",
        > 0 when a < b => "a は0 以上かつ0未満",
    };
    Console.WriteLine(consoleText);
}

型によるパターンマッチング

型によるパターンマッチングも可能で、 (これはSwich文でもできる) 例えば基底クラスMainとそれを継承したSubAとSubBというクラスがあるとき

public class Main
{
    public string MainParam { get; set; } = "";
}

public class SubA : Main
{
    public string SubParamA { get; set; } = "";
}

public class SubB : Main
{
    public string SubParamB { get; set; } = "";

以下のように、クラスによって処理を分岐できる

public static void SwitchExpressionDemo4(Main obj)
{
    string consoleText = obj switch
    {
        SubA => "SubA",
        SubB => "SubB",
        Main => "Main",
    };
    Console.WriteLine(consoleText);
}

網羅判定

Switch式の評価が網羅されているかの評価として 破棄パターン(_)を仕様しない方法がある

Switch式は破棄パターンは条件一致しないときの処理を行うが、
破棄パターンがなく、かつ条件網羅されていない場合はランタイムエラーが発生されるため、
条件網羅が容易になる

網羅チェック

この辺は、TypeScriptのnever形を使用したSwitch文の網羅チェックに近いものを感じる

参考