7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ApexのSwitchステートメントはいつ使えばいいのか?

Posted at

昔の話

昔Salesforceの開発を始めたばかりのころ、割合が0 ~ 10 %ならこれ、10 ~ 50 %ならこれ~のような分岐を書こうとしてSwitch文が使えないことに面倒だなーと驚いたことがありました。
時は流れてSummer'18リリースからSwitchステートメントが使用できるようになっていたものの、リリースノート読まない勢なのでしばらく使えることに気が付いていませんでした。

How to use

あまりに長い間使わなかったせいで、「だいたいIf-elseステートメントでも困らないよな」とか思ってましたが、最近コーディングする機会があったのでもっと使えそうな場所について考えてみようと思います。
基本構文はこんな感じ。

switch on expression {
    when value1 {		// when block 1
        // code block 1
    }	
    when value2 {		// when block 2
        // code block 2
    }
    when value3 {		// when block 3
        // code block 3
    }
    when else {		  // default block, optional
        // code block 4
    }
}

whenには1つの値、複数の値、sObjectを使用できるとのこと。

使用例

最初にSwitchステートメントを使おうかなーと思ったのは取引先ごとに各月の商談の金額を集計して、1レコードにまとめる処理を実装しようと思った時でした。
各レコードは以下のような形で集計するものとします。

取引先 年度 4月 5月 6月 7月 8月 9月 10月 11月 12月 1月 2月 3月
会社A 2018 ¥300 ¥300 ¥300 ¥300 ¥300 ¥300 ¥300 ¥300 ¥300 ¥300 ¥300 ¥300
会社A 2017 ¥200 ¥200 ¥200 ¥200 ¥200 ¥200 ¥200 ¥200 ¥200 ¥200 ¥200 ¥200
会社B 2018 ¥250 ¥200 ¥250 ¥200 ¥250 ¥200 ¥250 ¥200 ¥250 ¥200 ¥250 ¥200

1レコードの中に1~12月までのカスタム項目を作成しているので、If~elseステートメントの場合、以下のような方法で記載することになります。

Decimal january = 0;
Decimal february = 0;
Decimal march = 0;
Decimal april = 0;
Decimal may = 0;
Decimal june = 0;
Decimal july = 0;
Decimal august = 0;
Decimal september = 0;
Decimal october = 0;
Decimal nobember = 0;
Decimal december = 0;

for (Opportunity opp : opportunityList) {
    if (opp.CloseDate.month() == 1) {
        january += opp.Amount;
    } else if (opp.CloseDate.month() == 2) {
        february += opp.Amount;
    } else if (opp.CloseDate.month() == 3) {
        march += opp.Amount;
    } else if (opp.CloseDate.month() == 4) {
        april += opp.Amount;
    } else if (opp.CloseDate.month() == 5) {
        may += opp.Amount;
    } else if (opp.CloseDate.month() == 6) {
        june += opp.Amount;
    } else if (opp.CloseDate.month() == 7) {
        july += opp.Amount;
    } else if (opp.CloseDate.month() == 8) {
        august += opp.Amount;
    } else if (opp.CloseDate.month() == 9) {
        september += opp.Amount;
    } else if (opp.CloseDate.month() == 10) {
        october += opp.Amount;
    } else if (opp.CloseDate.month() == 11) {
        nobember += opp.Amount;
    } else {
        december += opp.Amount;
    }
}

一方でSwitchステートメントを使用すると、上記のコードは以下のように置き換えることができます。

Decimal january = 0;
Decimal february = 0;
Decimal march = 0;
Decimal april = 0;
Decimal may = 0;
Decimal june = 0;
Decimal july = 0;
Decimal august = 0;
Decimal september = 0;
Decimal october = 0;
Decimal nobember = 0;
Decimal december = 0;

for (Opportunity opp : opportunityList) {
    switch on opp.CloseDate.month() {
        when 1 { january += opp.Amount; }
        when 2 { february += opp.Amount; }
        when 3 { march += opp.Amount;}
        when 4 { april += opp.Amount; }
        when 5 { may += opp.Amount; }
        when 6 { june += opp.Amount; }
        when 7 { july += opp.Amount; }
        when 8 { august += opp.Amount; }
        when 9 { september += opp.Amount; }
        when 10 { october += opp.Amount; }
        when 11 { nobember += opp.Amount; }
        when else { december += opp.Amount; }
    }
}

これで可読性がだいぶ上がったような気がします。

他の使い道はどんなものがあるか?

whenの値をnullにすることができるとのことなので、例えば以下のように置き換えることができます。
これは結構便利そうです。

// If~elseステートメント
if (i != null) {
    if (i == 2) {
        System.debug('when block 2');
    } else {
        System.debug('default ' + i);
    }
} else {
    System.debug('bad integer');
}

// Switchステートメント
switch on i {
   when null { System.debug('bad integer'); }
   when 2 { System.debug('when block 2'); }
   when else { System.debug('default ' + i); }
}

また、メソッドコールの結果も利用できるので、思ったよりも利用の幅が多そうです。

// If~elseステートメント
Integer j = someInteger(i);
if (j == 2) {
    System.debug('when block 2');
} else if (j == 3) {
    System.debug('when block 3');
} else {
    System.debug('bad integer');
}

// Switchステートメント
switch on someInteger(i) {
   when 2 { System.debug('when block 2'); }
   when 3 { System.debug('when block 3'); }
   when else { System.debug('default'); }
}

システム上あまり意識したことがないのですが、そのうちどちらの処理の方が早いかについても調査してみようかなと思います。

参考

こちらは個人的に頭いいなーと思った使い方です。
トリガーの実装方法も含めてこんな考え方ができるようになりたいものです。

7
5
0

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
7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?