Switchケース:1つの数字の代わりに範囲を使用できますか


92

スイッチを使いたいのですが、ケースが多いのですが、近道はありますか?これまでのところ、私が知って試した唯一の解決策は次のとおりです。

switch (number)
{
case 1: something; break;
case 2: other thing; break;
...
case 9: .........; break;
}

私ができることを望んでいるのは、次のようなものです。

switch (number)
{
case (1 to 4): do the same for all of them; break;
case (5 to 9): again, same thing for these numbers; break;
}

1
そのようなシナリオにはif-elseを使用できます
Satpal 2013年

回答:


239

この質問のゲームには少し遅れていますが、C#7で導入された最近の変更(Visual Studio 2017 / .NET Framework 4.6.2でデフォルトで使用可能)では、switchステートメントを使用して範囲ベースの切り替えが可能になりました。

例:

int i = 63;

switch (i)
{
    case int n when (n >= 100):
        Console.WriteLine($"I am 100 or above: {n}");
        break;

    case int n when (n < 100 && n >= 50 ):
        Console.WriteLine($"I am between 99 and 50: {n}");
        break;

    case int n when (n < 50):
        Console.WriteLine($"I am less than 50: {n}");
        break;
}

ノート:

  • 括弧()when条件では必須ではありませんが、この例では比較を強調するために使用されています。
  • varの代わりに使用することもできますint。例:case var n when n >= 100:

10
あなたは、私のヒーローです。私はこれをいくつかの誓いの言葉で強調したかったのですが、そうではありませんでした。:)
Gawie Greef 2017

2
(そして)周りのwhen条件は不要です。つまりcase int n when n >= 100:、動作します。
UweKeim18年

6
でも、varすなわち:作業を行いますcase var n when n >= 100:
UweKeim18年

9
@JamesKo特に3〜4を超える条件がある場合は、多数のifステートメントと比較して、クリーンで読みやすさが向上すると思います。
サック

1
一連のifステートメントよりもはるかに優れており、はるかにクリーンです。
ジョンストック

44

これがあなたの問題ステートメントのためのより良くてエレガントな解決策です。

int mynumbercheck = 1000;
// Your number to be checked
var myswitch = new Dictionary <Func<int,bool>, Action>
            { 
             { x => x < 10 ,    () => //Do this!...  },  
             { x => x < 100 ,    () => //Do this!...  },
             { x => x < 1000 ,    () => //Do this!...  },
             { x => x < 10000 ,   () => //Do this!... } ,
             { x => x < 100000 ,  () => //Do this!... },
             { x => x < 1000000 ,  () => //Do this!... } 
            };

次に、条件付きスイッチを呼び出します

   myswitch.First(sw => sw.Key(mynumbercheck)).Value();

Switch / ifElseの代替


1
@AkxayaスイッチはC#で拡張する必要があると思いますが、これは素晴らしく見え、非常にうまく機能しているようです。この例を共有していただき、ありがとうございます。ありがとう
WonderWorker 2016年

これは、スイッチ/ケースの質問の範囲に対する明確な答えではありません。
ポインタヌル

13
ディクショナリは、値が追加された順序で格納および返されることはありません。これはMicrosoftコンパイラで機能しますが、機能しなかった場合に準拠コンパイラを簡単に作成できます。代わりに、List <KeyValuePair <Func <int、bool>、Action >>を使用してください。また、データ構造の生成にはコストがかかるため、静的な読み取り専用メンバーである必要があることにも注意してください。
ネイサンフィリップス

@PointerNull:今後の参考のためにコメントに書かれた必要なコードについては、ブログを参照してください
Akxaya 2017年

@NathanPhillips:これを持ってきてくれてありがとう。確かに、IListコレクションも代替手段になります。これは、List <t>を使用して複雑なパラメーターを使用して実装したサンプルにすぎません。
Akxaya 2017年

14

三項演算子を使用して、スイッチの状態を分類します。

そう...

switch( number > 9 ? "High" :
        number > 5 ? "Mid" :
        number > 1 ? "Low" : "Floor")
        {
              case "High":
                    do the thing;
                    break;
               case "Mid":
                    do the other thing;
                    break;
               case "Low":
                    do something else;
                    break;
               case "Floor":
                    do whatever;
                    break;
         }

13

スレッドを完了するために、C#8の構文を次に示します。

  var percent = price switch
  {
    var n when n >= 1000000 => 7f,
    var n when n >= 900000 => 7.1f,
    var n when n >= 800000 => 7.2f,
    _ => 0f // default value
  };

範囲を指定したい場合:

  var percent2 = price switch
  {
    var n when n >= 1000000 => 7f,
    var n when n < 1000000 && n >= 900000 => 7.1f,
    var n when n < 900000 && n >= 800000 => 7.2f,
    _ => 0f // default value
  };

8

その場合はif-elseを使用する必要がありますが、何らかの理由で切り替えが必要な場合は、次のように実行できます。ブレークのない最初のケースは、最初のブレークが発生するまで伝播します。以前の回答が示唆しているように、私はif-else overswitchをお勧めします。

switch (number){
            case 1:
            case 2:
            case 3:
            case 4: //do something;
                    break;
            case 5:
            case 6:
            case 7:
            case 8:
            case 9: //Do some other-thing;
                   break;
        }

8

境界のswitchaと組み合わせて使用​​することにより、「ハンドル」範囲を構築することができListます。

List<int> bounds = new List<int>() {int.MinValue, 0, 4, 9, 17, 20, int.MaxValue };

switch (bounds.IndexOf(bounds.Last(x => x < j)))
{
    case 0: // <=0
        break;

    case 1: // >= 1 and <=4
        break;
    case 2: // >= 5 and <=9
        break;
    case 3: // >= 10 and <=17
        break;
    case 4: // >= 18 and <=20
        break;

    case 5: // >20
        break;
}

このアプローチでは、範囲は異なるスパンを持つことができます。


6

間隔は一定です:

 int range = 5
 int newNumber = number / range;
 switch (newNumber)
 {
      case (0): //number 0 to 4
                break;
      case (1): //number 5 to 9
                break;
      case (2): //number 10 to 14
                break;
      default:  break;
 }

そうでなければ:

  if else

3

前述のようにif-else、この場合は範囲​​を処理する方がよいでしょう。

if(number >= 1 && number <= 4)
{
   //do something;
}
else if(number >= 5 && number <= 9)
{
   //do something else;
}

2

.NetではVisualBasicのみがswitchステートメントで範囲を許可しますが、C#ではこれに有効な構文はありません。

C#で特定の問題に取り組むと、次のように解決します。

if(number >= 1 && number <= 9) // Guard statement
{
    if(number < 5)
    {
        // Case (1 to 4):

        //break;

    }
    else
    {
        // Case (5 to 9):

        //break;

    }

}
else
{
    // Default code goes here

    //break;

}

これをさらに説明するために、パーセンテージ値があると想像してください。

問題をテンプレートとして使用すると、次のようになります。

switch (percentage)
{
    case (0 to 19):
        break;

    case (20 to 39):
        break;

    case (40 to 69):
        break;

    case (70 to 79):
        break;

    case (80 to 100):
        break;

    default:
        break;

}

ただし、C#ではその構文が許可されていないため、C#で許可されている解決策は次のとおりです。

if (percentage >= 0 && percentage <= 100) // Guard statement
{
    if (percentage >= 40)
    {
        if (percentage >= 80)
        {
            // Case (80% to 100%)

            //break;

        }
        else
        {
            if (percentage >= 70)
            {
                // Case (70% to 79%)

                //break;

            }
            else
            {
                // Case (40% to 69%)

                //break;

            }

        }

    }
    else
    {
        if (percentage >= 20)
        {
            // Case (20% to 39%)

            //break;

        }
        else
        {
            // Case (0% to 19%)

            //break;

        }

    }

}
else
{
    // Default code goes here

    //break;

}

慣れるまで少し時間がかかるかもしれませんが、慣れれば大丈夫です。

個人的には、範囲を許可するためのswitchステートメントを歓迎します。

C#switchステートメントの将来

switchステートメントを改善する方法について私が持っていたいくつかのアイデアは次のとおりです。

バージョンA

switch(value)
{
    case (x => x >= 1 && x <= 4):
    break;

    case (x => x >= 5 && x <= 9):
    break;

    default:
    break;

}

バージョンB

switch(param1, param2, ...)
{
    case (param1 >= 1 && param1 <= 4):
    break;

    case (param1 >= 5 && param1 <= 9 || param2 != param1):
    break;

    default:
    break;

}

1

C / C ++を使用する場合、「範囲」構文はありません。各「ケース」セグメントの後にのみ、すべての値をリストできます。言語AdaまたはPascalは範囲構文をサポートします。


0

まず、参照しているプログラミング言語を指定する必要があります。次に、switchステートメントは、列挙型や事前定義された文字列など、切り替えられた変数に関するオプションの閉集合に適切に使用されます。この場合、古き良きif-else構造を使用することをお勧めします。


0

switch場合によっては不可能です。ネストされたifステートメントを使用できます。

if(number>=1 && number<=4){
//Do something
}else if(number>=5 && number<=9){
//Do something
}

(number >= 1 && number <= 4)それぞれの番号をチェックする代わりに、古き良き時代はどうですか?1から120の間でどのように書きますか?;-)
DarkDust 2013年

ああ、そして=対に注意を払ってください==
DarkDust 2013年

-1

質問がCに関するものであった場合(あなたは言わなかった)、答えはノーですが、 GCCとClang(おそらく他の人)は範囲構文をサポートしていますが、それ有効なISO Cではありません

switch (number) {
    case 1 ... 4:
        // Do something.
        break;

    case 5 ... 9:
        // Do something else.
        break;
}

前後にスペースを...入れてください。そうしないと、構文エラーが発生します。


Pascal / delphiもこれを行います。1..4のケース番号:何かをする; など
Kell 2014

質問はC#についてです
SuB 2016年

@SuB:わかっています。OPが最終的に質問の言語を教えてくれた後、この質問にC#タグを追加しました。しかし、その答えは、検索エンジンを介してここに来る人々にとってはまだ役立つかもしれません。それが私がそれを削除していない理由です。
DarkDust 2016年

-1

C#の場合、switchケースは基本的に、次に何をすべきかについての辞書です。辞書で範囲を検索することはできないので、できる最善のことは、スティーブ・ゴメスが述べた場合です。


-3

||でif-elseステートメントを使用できます 次のような演算子(または演算子):

if(case1 == true || case2 == true || case3 == true)
   {
    Do this!... 
   }
else if(case4 == true || case5 == true || case6 == true)
   {
    Do this!... 
   }
else if(case7 == true || case8 == true || case9 == true)
   {
    Do this!... 
   }

うわー、それはのようなもののために少し複雑ですif (number >= 1 && number <= 4) { … } else if (number >= 5 && number <= 9) { … }、あなたは思いませんか?
DarkDust 2013年

ああ大丈夫はい...ええと、同じことをすることになっているケースが注文されていない場合は、 '||を使用する必要があります オペレーター '...
Lukas Warsitz 2013年

しかし、彼のポイントは、数値が範囲内にあるかどうかを確認することだったので、順序は重要ではありません(チェックされた範囲を除く)。
DarkDust 2013年

それは欠点ではありません、あなたの解決策は間違っていません、ただ複雑です;-)
DarkDust 2013年

==真:face_palm:これはデフォルトの動作であり、あなたがない演算子を使用することができ、偽==ため
Et7f3XIV
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.