680

case value:繰り返し述べずに複数のケースステートメントを通過する方法はありますか?

私はこれが機能することを知っています:

switch (value)
{
   case 1:
   case 2:
   case 3:
      // Do some stuff
      break;
   case 4:
   case 5:
   case 6:
      // Do some different stuff
      break;
   default:
       // Default stuff
      break;
}

しかし、私はこのようなことをしたいと思います:

switch (value)
{
   case 1,2,3:
      // Do something
      break;
   case 4,5,6:
      // Do something
      break;
   default:
      // Do the Default
      break;
}

私が考えているこの構文は別の言語からのものですか、それとも何か不足していますか?

4

23 に答える 23

785

これはすでに回答されていると思います。ただし、次のようにすることで、構文的により良い方法で両方のオプションを混在させることができると思います。

switch (value)
{
    case 1: case 2: case 3:          
        // Do Something
        break;
    case 4: case 5: case 6: 
        // Do Something
        break;
    default:
        // Do Something
        break;
}
于 2010-08-01T13:29:29.027 に答える
360

あなたが言及した2番目の方法には、C++にもC#にも構文はありません。

最初の方法に問題はありません。ただし、範囲が非常に大きい場合は、一連の if ステートメントを使用してください。

于 2008-09-16T01:40:32.557 に答える
74

この構文は、Visual Basic のSelect...Case ステートメントからのものです。

Dim number As Integer = 8
Select Case number
    Case 1 To 5
        Debug.WriteLine("Between 1 and 5, inclusive")
        ' The following is the only Case clause that evaluates to True.
    Case 6, 7, 8
        Debug.WriteLine("Between 6 and 8, inclusive")
    Case Is < 1
        Debug.WriteLine("Equal to 9 or 10")
    Case Else
        Debug.WriteLine("Not between 1 and 10, inclusive")
End Select

この構文は C# では使用できません。代わりに、最初の例の構文を使用する必要があります。

于 2008-09-16T01:41:50.493 に答える
37

あなたはあなたに与える改行を省くことができます:

case 1: case 2: case 3:
   break;

しかし、私はその悪いスタイルを考えます。

于 2008-09-16T03:11:37.313 に答える
21

.NET Framework 3.5 には範囲があります。

MSDN の Enumerable.Range

誰かが言ったように、SWITCH ステートメントは「==」演算子を使用するため、「contains」と IF ステートメントで使用できます。

ここに例があります:

int c = 2;
if(Enumerable.Range(0,10).Contains(c))
    DoThing();
else if(Enumerable.Range(11,20).Contains(c))
    DoAnotherThing();

しかし、もっと楽しいことができると思います: 戻り値は必要なく、このアクションはパラメーターを取らないので、簡単にアクションを使用できます!

public static void MySwitchWithEnumerable(int switchcase, int startNumber, int endNumber, Action action)
{
    if(Enumerable.Range(startNumber, endNumber).Contains(switchcase))
        action();
}

この新しいメソッドを使用した古い例:

MySwitchWithEnumerable(c, 0, 10, DoThing);
MySwitchWithEnumerable(c, 10, 20, DoAnotherThing);

値ではなくアクションを渡すため、括弧は省略してください。これは非常に重要です。引数付きの関数が必要な場合は、 の型を に変更するだけActionですAction<ParameterType>。戻り値が必要な場合は、 を使用しますFunc<ParameterType, ReturnType>

C# 3.0 では、case パラメーターが同じであるという事実をカプセル化する簡単な部分適用はありませんが、小さなヘルパー メソッドを作成します (少し冗長ですが)。

public static void MySwitchWithEnumerable(int startNumber, int endNumber, Action action){ 
    MySwitchWithEnumerable(3, startNumber, endNumber, action); 
}

これは、新しい機能的なインポートされたステートメントが、古い命令型ステートメントよりも強力でエレガントであることの例です。

于 2008-09-16T10:27:16.660 に答える
13

以下のコードは機能しません

case 1 | 3 | 5:
// Not working do something

これを行う唯一の方法は次のとおりです。

case 1: case 2: case 3:
// Do something
break;

探しているコードは、範囲を簡単に入力できるVisual Basicで機能します...ステートメントまたはブロックのnoneオプションで便利です。非常に極端な場合は、VisualBasicで.dllを作成してインポートし直すことをお勧めします。 C#プロジェクトに。switchif else

注:VisualBasicで同等のスイッチはSelect Caseです。

于 2012-11-04T00:03:55.193 に答える
8

別のオプションは、ルーチンを使用することです。ケース 1 ~ 3 のすべてが同じロジックを実行する場合は、そのロジックをルーチンにラップして、ケースごとに呼び出します。これで実際に case ステートメントが取り除かれるわけではないことはわかっていますが、適切なスタイルが実装され、メンテナンスが最小限に抑えられます.....

[編集]元の質問に一致する代替実装を追加...[/編集]

switch (x)
{
   case 1:
      DoSomething();
      break;
   case 2:
      DoSomething();
      break;
   case 3:
      DoSomething();
      break;
   ...
}

private void DoSomething()
{
   ...
}

代替

switch (x)
{
   case 1:
   case 2:
   case 3:
      DoSomething();
      break;
   ...
}

private void DoSomething()
{
   ...
}
于 2008-09-16T03:30:13.947 に答える
5

gccは、シーケンシャル範囲をサポートするためにC言語の拡張機能を実装しています。

switch (value)
{
   case 1...3:
      //Do Something
      break;
   case 4...6:
      //Do Something
      break;
   default:
      //Do the Default
      break;
}

編集:質問のC#タグに気付いたので、おそらくgccの回答は役に立ちません。

于 2008-09-16T02:59:52.583 に答える
5

C# でのswitchのあまり知られていない側面の 1 つは、 operator=に依存していることです。これはオーバーライドできるため、次のようにすることができます。


string s = foo();

switch (s) {
  case "abc": /*...*/ break;
  case "def": /*...*/ break;
}
于 2008-09-16T02:16:25.293 に答える
4

実際、私も GOTO コマンドは好きではありませんが、これは Microsoft の公式資料にあり、ここにすべての許可された構文があります。

switch セクションのステートメント リストの終点に到達できる場合、コンパイル エラーが発生します。これは、「失敗しない」ルールとして知られています。例

switch (i) {
case 0:
   CaseZero();
   break;
case 1:
   CaseOne();
   break;
default:
   CaseOthers();
   break;
}

到達可能な終点を持つスイッチ セクションがないため、有効です。C や C++ とは異なり、switch セクションの実行は、次の switch セクションに「フォール スルー」することはできません。

switch (i) {
case 0:
   CaseZero();
case 1:
   CaseZeroOrOne();
default:
   CaseAny();
}

コンパイル時エラーが発生します。switch セクションの実行の後に別の switch セクションを実行する場合は、明示的な goto case または goto default ステートメントを使用する必要があります。

switch (i) {
case 0:
   CaseZero();
   goto case 1;
case 1:
   CaseZeroOrOne();
   goto default;
default:
   CaseAny();
   break;
}

switch-section では複数のラベルを使用できます。例

switch (i) {
case 0:
   CaseZero();
   break;
case 1:
   CaseOne();
   break;
case 2:
default:
   CaseTwo();
   break;
}

この特定のケースでは、GOTO を使用することができ、それが実際に失敗する唯一の方法だと思います。

ソース

于 2011-09-08T08:21:39.153 に答える
3

You can also have conditions that are completely different

            bool isTrue = true;

            switch (isTrue)
            {
                case bool ifTrue when (ex.Message.Contains("not found")):
                case bool ifTrue when (thing.number = 123):
                case bool ifTrue when (thing.othernumber != 456):
                    response.respCode = 5010;
                    break;
                case bool ifTrue when (otherthing.text = "something else"):
                    response.respCode = 5020;
                    break;
                default:
                    response.respCode = 5000;
                    break;
            }
于 2021-02-10T14:13:48.887 に答える
3

非常に大量の文字列 (またはその他の型) のケースがすべて同じことをしている場合は、string.Contains プロパティと組み合わせた文字列リストを使用することをお勧めします。

したがって、次のような大きな switch ステートメントがある場合:

switch (stringValue)
{
    case "cat":
    case "dog":
    case "string3":
    ...
    case "+1000 more string": // Too many string to write a case for all!
        // Do something;
    case "a lonely case"
        // Do something else;
    .
    .
    .
}

if次のようなステートメントに置き換えることができます。

// Define all the similar "case" string in a List
List<string> listString = new List<string>(){ "cat", "dog", "string3", "+1000 more string"};
// Use string.Contains to find what you are looking for
if (listString.Contains(stringValue))
{
    // Do something;
}
else
{
    // Then go back to a switch statement inside the else for the remaining cases if you really need to
}

これは、任意の数の文字列ケースに対して適切にスケーリングされます。

于 2018-03-29T16:00:21.063 に答える
2

非常に多くの作業が、C#で最も使用されていない構文の1つを、どういうわけか見栄えを良くしたり、うまく機能させたりする方法を見つけるために費やされたようです。個人的には、switchステートメントを使用する価値はほとんどないと思います。テストしているデータと必要な最終結果を分析することを強くお勧めします。

たとえば、既知の範囲の値をすばやくテストして、それらが素数であるかどうかを確認するとします。コードに無駄な計算を行わせたくない場合は、オンラインで必要な範囲の素数のリストを見つけることができます。大規模なswitchステートメントを使用して、各値を既知の素数と比較できます。

または、素数の配列マップを作成して、すぐに結果を得ることができます。

    bool[] Primes = new bool[] {
        false, false, true, true, false, true, false,    
        true, false, false, false, true, false, true,
        false,false,false,true,false,true,false};
    private void button1_Click(object sender, EventArgs e) {
        int Value = Convert.ToInt32(textBox1.Text);
        if ((Value >= 0) && (Value < Primes.Length)) {
            bool IsPrime = Primes[Value];
            textBox2.Text = IsPrime.ToString();
        }
    }

文字列内の文字が16進数であるかどうかを確認したい場合があります。醜くてやや大きなswitchステートメントを使用できます。

または、正規表現を使用してcharをテストするか、IndexOf関数を使用して既知の16進文字の文字列でcharを検索することができます。

        private void textBox2_TextChanged(object sender, EventArgs e) {
        try {
            textBox1.Text = ("0123456789ABCDEFGabcdefg".IndexOf(textBox2.Text[0]) >= 0).ToString();
        } catch {
        }
    }

1から24の範囲の値に応じて、3つの異なるアクションのいずれかを実行するとします。一連のIFステートメントを使用することをお勧めします。そして、それが複雑になりすぎた場合(または、1〜90の範囲の値に応じて5つの異なるアクションなど、数値が大きくなった場合)、列挙型を使用してアクションを定義し、列挙型の配列マップを作成します。次に、この値を使用して配列マップにインデックスを付け、必要なアクションの列挙型を取得します。次に、IFステートメントの小さなセットまたは非常に単純なswitchステートメントのいずれかを使用して、結果の列挙値を処理します。

また、値の範囲をアクションに変換する配列マップの良いところは、コードで簡単に変更できることです。ハードワイヤードコードを使用すると、実行時に動作を簡単に変更することはできませんが、配列マップを使用すると簡単に変更できます。

于 2012-02-23T06:25:00.577 に答える
1

会話に付け加えると、.NET 4.6.2 を使用して、次のことも実行できました。コードをテストしたところ、うまくいきました。

以下のように、複数の「OR」ステートメントを実行することもできます。

            switch (value)
            {
                case string a when a.Contains("text1"):
                    // Do Something
                    break;
                case string b when b.Contains("text3") || b.Contains("text4") || b.Contains("text5"):
                    // Do Something else
                    break;
                default:
                    // Or do this by default
                    break;
            }

配列内の値と一致するかどうかを確認することもできます。

            string[] statuses = { "text3", "text4", "text5"};

            switch (value)
            {
                case string a when a.Contains("text1"):
                    // Do Something
                    break;
                case string b when statuses.Contains(value):                        
                    // Do Something else
                    break;
                default:
                    // Or do this by default
                    break;
            }
于 2019-07-03T00:32:08.727 に答える
1

それを処理するより美しい方法

if ([4, 5, 6, 7].indexOf(value) > -1)
    //Do something

同じ結果で複数の値に対してそれを行うことができます

于 2021-09-07T13:15:39.840 に答える
0

このアプローチを使用して、switch ステートメントで複数のケースを実現することもできます...このアプローチを使用すると、必要な数の条件を使用できます..

    int i = 209;
    int a = 0;
    switch (a = (i>=1 && i<=100) ? 1 : a){    
    case 1:
        System.out.println ("The Number is Between 1 to 100 ==> " + i);
        break;
    default:
        switch (a = (i>100 && i<=200) ? 2 : a) {
            case 2:
                System.out.println("This Number is Between 101 to 200 ==> " + i);
                break;
        
            default:
                switch (a = (i>200 && i<=300) ? 3 : a) {
                    case 3:
                        System.out.println("This Number is Between 201 to 300 ==> " + i);
                        break;
                
                    default:
                        // You can make as many conditions as you want;
                        break;
                }
        }
        
    }
于 2021-12-12T18:06:08.867 に答える
-6

これには、goto ステートメントを使用します。そのような:

    switch(value){
    case 1:
        goto case 3;
    case 2:
        goto case 3;
    case 3:
        DoCase123();
    //This would work too, but I'm not sure if it's slower
    case 4:
        goto case 5;
    case 5:
        goto case 6;
    case 6:
        goto case 7;
    case 7:
        DoCase4567();
    }
于 2011-07-09T22:41:49.140 に答える