it-swarm-vi.tech

Nhiều trường hợp trong câu lệnh switch

Có cách nào để vượt qua nhiều báo cáo trường hợp mà không nêu case value: nhiều lần không?

Tôi biết điều này hoạt động:

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;
}

nhưng tôi muốn làm một cái gì đó như thế này:

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

Là cú pháp này tôi đang nghĩ đến từ một ngôn ngữ khác, hoặc tôi đang thiếu một cái gì đó?

524
theo

Không có cú pháp trong C++ cũng như C # cho phương thức thứ hai mà bạn đã đề cập.

Không có gì sai với phương pháp đầu tiên của bạn. Tuy nhiên, nếu bạn có phạm vi rất lớn, chỉ cần sử dụng một loạt các câu lệnh if.

287
Brian R. Bondy

Tôi đoán điều này đã được trả lời. Tuy nhiên, tôi nghĩ rằng bạn vẫn có thể kết hợp cả hai tùy chọn theo cách cú pháp tốt hơn bằng cách thực hiện:

switch (value)
{
case 1: case 2: case 3:          
    // Do Something
    break;
case 4: case 5: case 6: 
    // Do Something
    break;
default:
    // Do Something
    break;
}
643
Carlos Quintanilla

Cú pháp này là từ Visual Basic Chọn ... Báo cáo trường hợp :

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

Bạn không thể sử dụng cú pháp này trong C #. Thay vào đó, bạn phải sử dụng cú pháp từ ví dụ đầu tiên của bạn.

68
Neal

Hơi muộn cho câu hỏi ban đầu, nhưng tôi đăng câu trả lời này với hy vọng ai đó sử dụng phiên bản mới hơn ( C # 7 - có sẵn theo mặc định trong Visual Studio 2017/.NET Framework 4.6 .2 ), sẽ thấy hữu ích.

Trong C # 7, chuyển đổi dựa trên phạm vi hiện có thể thực hiện với câu lệnh chuyển đổi và sẽ giúp giải quyết vấn đề của OP.

Ví dụ:

int i = 5;

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

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

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

// Output: I am between 4 and 6: 5

Ghi chú:

  • Các dấu ngoặc đơn () không bắt buộc trong điều kiện when, nhưng được sử dụng trong ví dụ này để làm nổi bật (các) so sánh.
  • var cũng có thể được sử dụng thay cho int. Ví dụ: case var n when n >= 7:.
47
Steve Gomez

Bạn có thể bỏ qua dòng mới cung cấp cho bạn:

case 1: case 2: case 3:
   break;

nhưng tôi coi đó là phong cách xấu.

31
Allan Wind

.NET Framework 3.5 có các phạm vi:

Có thể đếm được. Thay đổi từ MSDN

bạn có thể sử dụng nó với "chứa" và câu lệnh IF, vì giống như ai đó đã nói câu lệnh SWITCH sử dụng toán tử "==".

Dưới đây là một ví dụ:

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

Nhưng tôi nghĩ chúng ta có thể vui hơn: vì bạn sẽ không cần các giá trị trả về và hành động này không lấy tham số, bạn có thể dễ dàng sử dụng các hành động!

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

Ví dụ cũ với phương thức mới này:

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

Vì bạn đang truyền hành động, không phải giá trị, bạn nên bỏ dấu ngoặc đơn, điều này rất quan trọng. Nếu bạn cần hàm với các đối số, chỉ cần thay đổi loại Action thành Action<ParameterType>. Nếu bạn cần giá trị trả về, hãy sử dụng Func<ParameterType, ReturnType>.

Trong C # 3.0, không dễ dàng Ứng dụng một phần để đóng gói thực tế tham số trường hợp là như nhau, nhưng bạn tạo một phương thức trợ giúp nhỏ (một chút dài dòng, tho).

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

Dưới đây là một ví dụ về cách tuyên bố nhập khẩu chức năng mới IMHO mạnh mẽ và thanh lịch hơn so với mệnh lệnh cũ.

18
Luca Molteni

@ Jennifer Owens: bạn hoàn toàn đúng mã dưới đây sẽ không hoạt động:

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

Cách duy nhất để làm điều này là:

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

Mã bạn đang tìm kiếm hoạt động trên cơ sở trực quan, nơi bạn có thể dễ dàng đặt phạm vi ... trong bất kỳ tùy chọn chuyển đổi nào hoặc nếu khối khác thuận tiện, tôi đề nghị, ở điểm cực kỳ, tạo ra cơ bản trực quan và nhập lại đến dự án c # của bạn.

Lưu ý: chuyển đổi tương đương trong cơ bản trực quan là trường hợp chọn.

8
none

Một lựa chọn khác là sử dụng một thói quen. Nếu các trường hợp 1-3 tất cả thực hiện cùng một logic thì bọc logic đó trong một thói quen và gọi nó cho từng trường hợp. Tôi biết điều này không thực sự thoát khỏi các báo cáo trường hợp, nhưng nó thực hiện phong cách tốt và duy trì ở mức tối thiểu .....

[Chỉnh sửa] Đã thêm triển khai thay thế để phù hợp với câu hỏi ban đầu ... [/ Chỉnh sửa]

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

private void DoSomething()
{
   ...
}

Alt

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

private void DoSomething()
{
   ...
}
7
Dr8k

Đây là giải pháp C # 7 hoàn chỉnh ...

switch (value)
{
   case var s when new[] { 1,2,3 }.Contains(s):
      //Do Something
      break;
   case var s when new[] { 4,5,6 }.Contains(s):
      //Do Something
      break;
   default:
      //Do the Default
      break;
}

Hoạt động với chuỗi quá ...

switch (mystring)
{
   case var s when new[] { "Alpha","Beta","Gamma" }.Contains(s):
      //Do Something
      break;
...
}
6
Carter Medlin

gcc triển khai một phần mở rộng cho ngôn ngữ C để hỗ trợ các phạm vi tuần tự:

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

Chỉnh sửa: Chỉ cần chú ý thẻ C # trong câu hỏi, vì vậy có lẽ câu trả lời gcc không có ích.

5
DGentry

Một khía cạnh ít được biết đến của switch trong C # là nó phụ thuộc vào toán tử = và vì nó có thể bị ghi đè nên bạn có thể có một cái gì đó như thế này:


string s = foo();

switch (s) {
  case "abc": /*...*/ break;
  case "def": /*...*/ break;
}
5
Cyber Oliveira

Thật ra tôi cũng không thích lệnh GOTO, nhưng đó là trong các tài liệu chính thức của MS, đây là tất cả các cú pháp được phép.

Nếu điểm cuối của danh sách câu lệnh của phần chuyển đổi có thể truy cập được, sẽ xảy ra lỗi thời gian biên dịch. Điều này được gọi là quy tắc "không rơi qua". Ví dụ

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

là hợp lệ vì không có phần chuyển đổi có điểm kết thúc có thể tiếp cận. Không giống như C và C++, việc thực hiện phần chuyển đổi không được phép "chuyển qua" sang phần chuyển đổi tiếp theo và ví dụ

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

dẫn đến một lỗi thời gian biên dịch. Khi thực hiện phần chuyển đổi phải được theo sau bằng cách thực hiện phần chuyển đổi khác, phải sử dụng trường hợp goto rõ ràng hoặc câu lệnh mặc định goto:

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

Nhiều nhãn được cho phép trong một phần chuyển đổi. Ví dụ

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

Tôi tin rằng trong trường hợp cụ thể này, GOTO có thể được sử dụng, đó thực sự là cách duy nhất để vượt qua.

nguồn: http://msdn.Microsoft.com/en-us/l Library/aa664749% 28v = vs.71% 29.aspx

3
Jiří Herník

Rất nhiều công việc khủng khiếp dường như đã được đưa vào để tìm cách lấy một trong những cú pháp ít được sử dụng nhất của C # để bằng cách nào đó trông đẹp hơn hoặc hoạt động tốt hơn. Cá nhân tôi thấy câu lệnh chuyển đổi hiếm khi sử dụng. Tôi đặc biệt khuyên bạn nên phân tích dữ liệu nào bạn đang kiểm tra và kết quả cuối cùng mà bạn muốn.

Hãy để chúng tôi nói ví dụ bạn muốn kiểm tra nhanh các giá trị trong một phạm vi đã biết để xem chúng có phải là số nguyên tố hay không. Bạn muốn tránh việc mã của bạn thực hiện các phép tính lãng phí và bạn có thể tìm thấy một danh sách các số nguyên tố trong phạm vi bạn muốn trực tuyến. Bạn có thể sử dụng câu lệnh chuyển đổi lớn để so sánh từng giá trị với các số nguyên tố đã biết.

Hoặc bạn chỉ có thể tạo một bản đồ mảng các số nguyên tố và nhận được kết quả ngay lập tức:

    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();
        }
    }

Có lẽ bạn muốn xem nếu một ký tự trong chuỗi là thập lục phân. Bạn có thể sử dụng một câu lệnh chuyển đổi vô duyên và hơi lớn.

Hoặc bạn có thể sử dụng một trong hai biểu thức chính quy để kiểm tra char hoặc sử dụng hàm IndexOf để tìm kiếm char trong một chuỗi các chữ cái thập lục phân đã biết:

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

Giả sử bạn muốn thực hiện một trong 3 hành động khác nhau tùy thuộc vào một giá trị sẽ nằm trong phạm vi từ 1 đến 24. Tôi sẽ đề nghị sử dụng một tập hợp các câu lệnh IF. Và nếu điều đó trở nên quá phức tạp (Hoặc các số lớn hơn, chẳng hạn như 5 hành động khác nhau tùy thuộc vào một giá trị trong phạm vi từ 1 đến 90), thì hãy sử dụng một enum để xác định các hành động và tạo một bản đồ mảng của enum. Giá trị sau đó sẽ được sử dụng để lập chỉ mục vào bản đồ mảng và nhận được liệt kê của hành động bạn muốn. Sau đó sử dụng một tập hợp nhỏ các câu lệnh IF hoặc một câu lệnh chuyển đổi rất đơn giản để xử lý giá trị enum kết quả.

Ngoài ra, điều thú vị về bản đồ mảng chuyển đổi một loạt các giá trị thành hành động là nó có thể dễ dàng thay đổi bằng mã. Với mã có dây cứng, bạn không thể dễ dàng thay đổi hành vi trong thời gian chạy nhưng với bản đồ mảng thì thật dễ dàng.

2
Darin

Nếu bạn có số lượng chuỗi rất lớn (hoặc bất kỳ loại nào khác) Trường hợp đều làm điều tương tự, tôi khuyên bạn nên sử dụng Danh sách chuỗi kết hợp với thuộc tính chuỗi.

Vì vậy, nếu bạn có một tuyên bố chuyển đổi lớn như vậy:

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;
    .
    .
    .
}

Bạn có thể muốn thay thế nó bằng một câu lệnh if như thế này:

//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
}

Thang đo này tốt cho bất kỳ số lượng các trường hợp chuỗi.

1
Maxter

Chỉ cần thêm vào cuộc trò chuyện, sử dụng .NET 4.6.2 tôi cũng có thể làm như sau. Tôi đã kiểm tra mã và nó đã làm việc cho tôi.

Bạn cũng có thể thực hiện nhiều câu lệnh "HOẶC", như dưới đây:

            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;
            }

Bạn cũng có thể kiểm tra xem nó có khớp với một giá trị trong một mảng không:

            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;
            }
0
JeffS