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


582

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

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ì đó?


Có lý do gì bạn không chỉ sử dụng câu lệnh IF (nếu bạn đang kiểm tra một phạm vi số nguyên)?
Eric Schoonover

2
vâng charlse, cách đầu tiên hoạt động tốt, tôi đã sử dụng nó ở nhiều nơi. Nó bẩn hơn tôi muốn, nhưng nó rất hữu ích. Tôi chỉ sử dụng những số nguyên đó làm ví dụ. Dữ liệu thực tế đã thay đổi nhiều hơn. Một if (1 | | 2 || 3) {...} khác nếu (4 || 5 || 6) {...} cũng sẽ hoạt động, nhưng khó đọc hơn.
theo

5
Tại sao bạn coi cái sau bẩn hơn cái trước. Cái sau thêm một ý nghĩa khác ,và một nghĩa không được chia sẻ với bất kỳ ngôn ngữ kiểu c nào khác. Điều đó có vẻ bẩn hơn đối với tôi.
Jon Hanna

1
Bạn có thể đã chọn cú pháp thứ 2 từ Ruby. Đó là cách nó hoạt động trong ngôn ngữ đó (mặc dù chuyển đổi trở thành trường hợp và trường hợp trở thành khi, trong số những thứ khác.)
juanpaco

4
Lưu ý quan trọng . Phạm vi được hỗ trợ trong trường hợp chuyển đổi bắt đầu C # v7 - Vui lòng xem câu trả lời
RBT

Câu trả lời:


313

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.


5
Ngoài ra, tôi muốn thêm một liên kết đến đặc tả ngôn ngữ C # có sẵn trên MSDN tại msdn.microsoft.com/en-us/vcsharp/aa336809.aspx
Richard McGuire

Người dùng có thể sử dụng một số if (hoặc tra cứu bảng) để giảm đầu vào thành một bộ enum và bật enum.
Harvey

5
có lẽ đã chọn nó từ VB.net
George Birbilis

1
VB.net tốt hơn cho các báo cáo trường hợp khác nhau ... ngoại trừ chúng không bỏ qua như C #. Lấy một ít, cho một ít.
Brain2000

Tôi tin rằng điều này không còn đúng nữa. Xem stackoverflow.com/questions/20147879/ cấp . Cũng trong câu hỏi này, có một câu trả lời stackoverflow.com/a/44848705/1073157
Dan Rayson

700

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

3
'Công tắc' nên viết thường cho c #?
Austin Harris

3
Mã được thu gọn được kéo dài đến ví dụ đầu tiên trong câu hỏi. Cũng có thể chỉ cần làm theo cách nó trong câu hỏi.
MetalPhoenix

10
Quan tâm làm gì? Công cụ tự động trong Visual Studio 2013 sẽ hoàn nguyên định dạng này trong định dạng ban đầu.
Gustav

14
@T_D nó nhận được hỗ trợ vì nó thực sự trả lời câu hỏi. OP nói, tôi có thiếu thứ gì không ... Carlos trả lời với những gì anh ta đang thiếu. Có vẻ khá cắt và khô với tôi. Đừng ghét rằng anh ấy đã nhận được 422 lượt upvote.
Mike Devenney 30/03/2016

8
@MikeDevenney Sau đó, bạn diễn giải câu hỏi khác đi, theo như tôi thấy câu trả lời đúng sẽ là "không, c # không có bất kỳ cú pháp nào cho điều đó". Nếu ai đó hỏi "có thể đổ chất lỏng vào ly tôi đang lộn ngược không?" câu trả lời nên là "không" và không "bạn có thể đổ chất lỏng lên nếu bạn nhìn nó lộn ngược và sử dụng trí tưởng tượng của bạn", bởi vì câu trả lời này hoàn toàn là về việc sử dụng trí tưởng tượng. Nếu bạn sử dụng cú pháp thông thường nhưng định dạng sai thì nó trông giống như cú pháp khác, với một số trí tưởng tượng. Hy vọng bạn hiểu ý tôi ...: P
T_D

74

Cú pháp này là từ Visual Basic Chọn ... Case Statement :

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.


49
đây là một trong số ít những điều tôi nhớ về * Cơ bản.
nickf

10
Ở đây chúng tôi có một trong số ít màn hình hiển thị trong đó cơ bản trực quan không xấu và linh hoạt hơn c #. Đây là một ví dụ có giá trị!
bgmCoder

Điều này là khá tốt. Tôi tự hỏi tại sao điều này chưa được thêm vào với C # 8.0. Sẽ khá đẹp.
Sigex

69

Trong C # 7 (có sẵn theo mặc định trong Visual Studio 2017 / .NET Framework 4.6.2), giờ đây có thể chuyển đổi dựa trên phạm vi với câu lệnh chuyển đổi và sẽ giúp giải quyết vấn đề của OP.

Thí 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 trongwhen điều kiện, nhưng được sử dụng trong ví dụ này để làm nổi bật (các) so sánh.
  • varcũng có thể được sử dụng thay cho int. Ví dụ : case var n when n >= 7:.

3
Điều này (khớp mẫu) thường là cách thực hành tốt nhất khi bạn có thể sử dụng C # 7.x trở lên, vì nó rõ ràng hơn nhiều so với các câu trả lời khác.
UndyingJellyfish

Có cách nào để đạt được điều này với một danh sách Enums không? Bản đồ Enums đến int ở đâu?
Sigex

33

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.


20

.NET Framework 3.5 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 Actionthành Action<ParameterType>. Nếu bạn cần giá trị trả về, sử dụng Func<ParameterType, ReturnType>.

Trong C # 3.0, không có Ứng dụng một phần dễ dàng nào để đóng gói thực tế là tham số trường hợp giống 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ũ.


3
Sự lựa chọn tốt. Mặc dù vậy, một điều cần lưu ý - Enumerable.Range có các đối số int startint count. Ví dụ của bạn sẽ không hoạt động đúng như cách chúng được viết. Bạn viết nó như thể đối số thứ hai là int end. Ví dụ: Enumerable.Range(11,20)sẽ dẫn đến 20 số bắt đầu bằng 11 và không phải các số từ 11 đến 20.
Gabriel McAdams

Mặc dù, nếu làm việc với Enum, tại sao không phải như thế? if (Enumerable.Range (MyEnum.A, MyEnum.M) {DoThing ();} khác if (Enumerable.Range (MyEnum.N, MyEnum.Z) {DoAnotherThing ();}
David Hollowell - MSFT

4
Lưu ý rằng Enumerable.Range(11,20).Contains(c)tương đương với for(int i = 11; i < 21; ++i){ if (i == c) return true; } return false;Nếu bạn có một phạm vi lớn, sẽ mất nhiều thời gian, trong khi chỉ cần sử dụng ><sẽ nhanh chóng và liên tục.
Jon Hanna

Một cải tiến: Có MySwitchWithEnumerabletrở lại voidlà thiết kế yếu cho tình huống này. LÝ DO: Bạn đã chuyển đổi if-elsemột loạt các tuyên bố độc lập - che giấu ý định, đó là chúng loại trừ lẫn nhau - chỉ có một actionđược thực thi. Thay vào đó trở lại bool, với cơ thể if (..) { action(); return true; } else return false;Trang web gọi sau đó hiển thị ý định : if (MySwitchWithEnumerable(..)) else (MySwitchWithEnumerable(..));. Điều này là thích hợp hơn. Tuy nhiên, nó cũng không còn là một cải tiến đáng kể so với phiên bản gốc của bạn, đối với trường hợp đơn giản này.
ToolmakerSteve

15

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

Nó cũng hoạt động với chuỗi ...

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

Điều này có nghĩa là bạn phân bổ các mảng với mỗi câu lệnh chuyển đổi, phải không? Sẽ không tốt hơn nếu chúng ta có chúng là các biến không đổi?
MaLiN2223

Thanh lịch, nhưng thực sự sẽ rất tốt nếu biết trình biên dịch tối ưu hóa kịch bản này sao cho các lệnh lặp đi lặp lại không phát sinh chi phí xây dựng mảng mỗi lần; xác định các mảng trước thời hạn là một lựa chọn, nhưng lấy đi phần lớn sự thanh lịch.
mkuity0

11

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 trong Visual Basic nơi bạn có thể dễ dàng đặt trong phạm vi ... trong nonetùy chọn của switchcâu lệnh hoặcif else khối thuận tiện, tôi đề nghị, ở điểm cực kỳ, tạo ra với Visual Basic và nhập lại đến dự án C # của bạn.

Lưu ý: công tắc tương đương trong Visual Basic là Select Case.


7

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à giữ cho bảo 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()
{
   ...
}

5

Một khía cạnh ít được biết đến của công tắc trong C # là nó phụ thuộc vào toán tử = và vì nó có thể bị ghi đè, 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;
}

4
điều này có thể trở thành một vấn đề lớn sau này đối với người khác đang cố đọc mã
Andrew Harry

5

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.


4

Trong C # 7, chúng tôi hiện có Kết hợp mẫu để bạn có thể thực hiện một số việc như:

switch (age)
{
  case 50:
    ageBlock = "the big five-oh";
    break;
  case var testAge when (new List<int>()
      { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 }).Contains(testAge):
    ageBlock = "octogenarian";
    break;
  case var testAge when ((testAge >= 90) & (testAge <= 99)):
    ageBlock = "nonagenarian";
    break;
  case var testAge when (testAge >= 100):
    ageBlock = "centenarian";
    break;
  default:
    ageBlock = "just old";
    break;
}

3

Trên thực tế 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 Microsoft và đâ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 và đó 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


Lưu ý rằng trong thực tế, gotohầu như luôn luôn có thể tránh được (mặc dù tôi không coi nó là "khủng khiếp" ở đây - nó đang lấp đầy một vai trò cụ thể, có cấu trúc,). Trong ví dụ của bạn, vì bạn đã bọc các thân case trong các hàm (một điều tốt), trường hợp 0 ​​có thể trở thành CaseZero(); CaseZeroOrOne(); break;. Không gotoyêu cầu.
ToolmakerSteve

Liên kết bị hỏng một nửa (chuyển hướng, "Tài liệu kỹ thuật đã nghỉ hưu của Visual Studio 2003" ).
Peter Mortensen

2

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 hay ho về một bản đồ mảng chuyển đổi một loạt các giá trị thành các 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.


Bạn cũng có thể ánh xạ tới biểu thức lambda hoặc một đại biểu
Conrad Frix

Điểm tốt. Một nhận xét nhỏ: Tôi thường thấy dễ dàng duy trì một danh sách các giá trị khớp với một trường hợp nhất định, hơn là một bản đồ mảng. Vấn đề với bản đồ mảng là rất dễ mắc lỗi. Ví dụ, thay vì bản đồ mảng số nguyên tố của true / falses, chỉ cần có một danh sách các số nguyên tố và tải chúng vào Hashset để thực hiện tra cứu. Ngay cả khi có nhiều hơn hai trường hợp, thường là tất cả trừ một trường hợp là một danh sách nhỏ, do đó, hãy xây dựng một Hashset của enums (nếu thưa thớt) hoặc một bản đồ mảng, từ mã, từ danh sách các trường hợp khác.
ToolmakerSteve

1

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

Điều này không phụ thuộc vào phiên bản C #, không phải phiên bản .NET?
Peter Mortensen

1

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) đề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 iftuyên bố 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.



-5

Đối với điều này, bạn sẽ sử dụng một tuyên bố goto. Nhu la:

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

7
@scone goto phá vỡ một hiệu trưởng cơ bản của lập trình thủ tục (trong đó c ++ và c # vẫn được bắt nguồn từ; chúng không phải là ngôn ngữ OO thuần túy (cảm ơn Chúa)). Lập trình thủ tục có một luồng logic được xác định rõ được xác định bởi các cấu trúc ngôn ngữ và các quy ước gọi phương thức (cách ngăn xếp thời gian chạy phát triển và thu hẹp). Về cơ bản, câu lệnh goto phá vỡ luồng này bằng cách cho phép nhảy xung quanh tùy ý.
samis

1
Tôi không nói rằng đó là phong cách tốt, sự cố chấp, nhưng nó thực hiện những gì câu hỏi ban đầu được yêu cầu.
scone

2
Không, nó không "làm những gì câu hỏi ban đầu được yêu cầu". Câu hỏi ban đầu có mã làm việc như là . Họ không cần sửa nó. Và ngay cả khi họ đã làm, đây là một gợi ý khủng khiếp. Nó ít súc tích, và sử dụng goto. Tồi tệ hơn, đó là một cách sử dụng hoàn toàn không cần thiết goto, vì cú pháp ban đầu được OP nêu ra hoạt động. Câu hỏi là liệu có cách nào ngắn gọn hơn để đưa ra các trường hợp thay thế. Như mọi người đã trả lời nhiều năm trước khi bạn làm , vâng, có - nếu bạn sẵn sàng đặt một vài trường hợp trên một dòng case 1: case 2:và nếu kiểu tự động của trình chỉnh sửa cho phép.
ToolmakerSteve

Lý do duy nhất khiến goto bị xác định là xấu là vì một số người cảm thấy khó theo dòng chảy logic. .Net MSIL (mã đối tượng được lắp ráp) sử dụng goto khắp nơi vì nó nhanh, nhưng nếu mã .Net có thể được viết và chỉ là trình diễn mà không có chúng thì tốt hơn là không sử dụng chúng và vì vậy bạn không bị mọi người như @ Trả lời hạ thấp của ToolmakerSteve.
Dynamiclynk

@wchoward - Xin vui lòng đọc trả lời của tôi cẩn thận hơn. Khiếu nại của tôi không chỉ là về việc sử dụng goto . Tôi phản đối vì câu hỏi cho thấy mã đã hoạt động như vậy và câu trả lời này a) lấy mã làm việc đó và làm cho nó dài dòng hơn, và ít cấu trúc hơn, không có lợi , b) không trả lời câu hỏi.
ToolmakerSteve
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.