フォールスルーのいろいろ
switch文でよく話題に出てくるフォールスルーだけど、言語によって実は結構違う。
// 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#では、JavaやC++と違い、フォールスルーはコンパイルエラーとなるため、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'を返す。
XSLTもSQLと同じく、最初に真となった部分のみが評価されるため、
<?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と同じ感じだったと思う。眠いから後で調べる。