フォールスルーのいろいろ

switch文でよく話題に出てくるフォールスルーだけど、言語によって実は結構違う。


まずはJavaC++

// Java
int i = 0;
switch (i) {
case 0: System.out.println("0");
case 1: System.out.println("1"); break;
}
// C++
int i = 0;
switch (i) {
case 0: std::cout << "0" << std::endl;
case 1: std::cout << "1" << std::endl; break;

これらは、フォールスルーを許すので、0と1が出力される。


次にC#

// C#
int i = 0;
switch (i)
{
    // これはひどい間違い。普通に無限ループに陥る
    // case 0: System.Console.WriteLine("0"); goto case 0;
    case 0: System.Console.WriteLine("0"); goto case 1;
    case 1: System.Console.WriteLine("1"); break;
}

C#では、JavaC++と違い、フォールスルーはコンパイルエラーとなるため、gotoで明示的に行う必要がある。


次にSQL

WITH Test(i) AS (SELECT 0)
SELECT CASE WHEN i = 0 THEN '0' WHEN i IN(0, 1) THEN '1' ELSE 'other' END
FROM Test;

SQLでは、フォールスルーは行われず、最初に真となった部分のみが評価されるため、上のSELECT文は'0'を返す。
XSLTSQLと同じく、最初に真となった部分のみが評価されるため、

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version = "1.0">
  <xsl:template match="/">
    <xsl:choose>
      <xsl:when test="0=0">
      </xsl:when>
      <xsl:when test="0=0">
        hoge
      </xsl:when>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

このコードはhogeを出力しない


ぱっと見、C#が明示的でいいかなー、と思うんだけど、これ、もちろんフォールスルー以外にも使えてしまう。
ので、フォールスルーしたければコメント書くのが一番かな。
いや、フォールスルーしたいってことは共通処理があるって事だから、メソッドとして切り出すほうがいいか。


Pythonは・・・Pythonはswitchないのでこんなこと考える必要ないです!
RubyはたぶんSQLと同じ感じだったと思う。眠いから後で調べる。