Phá vỡ trường hợp mặc định trong chuyển đổi


88

Tôi hơi bối rối về bất cứ khi nào hoặc không bao gồm breaksau trường hợp cuối cùng, thường xuyên default.

switch (type) {
    case 'product':

        // Do behavior

        break;
    default:

        // Do default behavior

        break; // Is it considered to be needed?
}

breakMục đích duy nhất của tôi là theo cách hiểu của tôi để ngăn chặn mã chạy qua phần còn lại của switchvali.

Sau đó, nó được coi là hợp lý hơn để có một breakcuối cùng do tính nhất quán hoặc bỏ qua có nó do breakáp dụng không sử dụng chức năng gì? Cả hai đều hợp lý theo những cách khác nhau theo ý kiến ​​của tôi.

Điều này có thể ở một mức độ nhất định được so sánh với việc kết thúc một .phptập tin với ?>. Tôi không bao giờ kết thúc với ?>phần lớn là do rủi ro xuất ra các khoảng trống, nhưng người ta có thể lập luận rằng đó sẽ là điều hợp lý để kết thúc tệp.

Câu trả lời:


144

breakkhông cần thiết về mặt kỹ thuật sau giải pháp thay thế cuối cùng (mà theo bạn, không cần phải như vậy default: nó hoàn toàn hợp pháp và đôi khi còn hữu ích để đặt defaultchi nhánh lên hàng đầu); liệu mã của bạn rơi vào cuối switchcâu lệnh hay breaksở cuối nhánh cuối cùng của nó có cùng kết quả hay không.

Tuy nhiên, tôi vẫn kết thúc mọi chi nhánh, kể cả chi nhánh cuối cùng, bằng một tuyên bố returnhoặc break, vì ba lý do:

  1. Tái cấu trúc. Nếu tất cả các chi nhánh của bạn kết thúc bằng breakhoặc return, bạn có thể sắp xếp lại chúng mà không thay đổi ý nghĩa. Điều này làm cho nó ít có khả năng sắp xếp lại như vậy để đưa ra hồi quy.
  2. Kiên định, và ít ngạc nhiên nhất. Tính nhất quán nói rằng các chi nhánh của bạn nên kết thúc một cách nhất quán, trừ khi chúng thực sự khác nhau về ý nghĩa. Nguyên lý bất ngờ tối thiểu cho rằng những thứ tương tự sẽ trông giống nhau. Kết thúc nhánh cuối cùng của một switchkhối chính xác như các khối trước đáp ứng cả hai, điều này giúp cho việc đọc và hiểu dễ dàng hơn. Nếu bạn bỏ qua phần rõ ràng break, nhánh cuối cùng sẽ khác về mặt quang học (điều đặc biệt quan trọng đối với việc quét nhanh) và để thấy rằng nó thực sự không khác biệt, người đọc phải hạ xuống mức độ khó đọc của từng câu lệnh .
  3. Bảo vệ chính mình. Nếu bạn tạo thói quen kết thúc tất cả các switchchi nhánh của mình bằng một break, nó sẽ tự động trở lại sau một thời gian và bạn sẽ ít có khả năng vô tình quên nó ở nơi có vấn đề. Rèn luyện bản thân để mong đợi breakở cuối mỗi chi nhánh cũng giúp phát hiện các breakcâu lệnh bị thiếu , rất tốt cho việc gỡ lỗi và khắc phục sự cố.

Cảm ơn cho cái nhìn sâu sắc của bạn trong này! Sẽ breaklà trường hợp cuối cùng :)
Robin Castlin

7
Trong C #, break(hoặc câu lệnh dòng điều khiển khác thoát khỏi case) cần thiết về mặt kỹ thuật sau lần thay thế cuối cùng.
dan04

3
@ dan04: vâng, điểm tốt. C # là một ngoại lệ ở đây, và có lẽ là do các nhà thiết kế ngôn ngữ biết về các vấn đề liên quan switchđến ngôn ngữ hiện có và muốn ngăn chặn chúng. Các quy tắc C # áp đặt khá nhiều phù hợp với các khuyến nghị từ câu trả lời của tôi.
tdammers

Ngôn ngữ nào bạn đang nói về cụ thể? C? C ++? C #? Java? PHP?
Svick

2
Một trình biên dịch tốt sẽ coi trận chung kết breaklà NO-OP thay vì tạo ra jmplệnh tiếp theo, đúng không?
Nathan Osman

11

Do sự mơ hồ tồn tại xung quanh việc sử dụng switch-casetrong hầu hết các ngôn ngữ, khi sử dụng nó, tôi sẽ đề nghị luôn luôn sử dụng một breakcâu lệnh, ngoại trừ khi nó không rõ ràng và theo thiết kế không muốn .

Một phần điều này là do làm cho mọi casecuộc gọi trông giống nhau, mà theo tôi sẽ cải thiện khả năng đọc. Nhưng điều đó cũng có nghĩa là nếu ai đó (thậm chí là bạn) chọn chèn casesau cái cuối cùng ở giai đoạn sau, họ không cần quan tâm đến việc kiểm tra khối trước, điều này có thể giúp giảm lỗi khi thêm mã mới.


7
Khi tôi muốn một trường hợp rơi vào trường hợp tiếp theo (và đó không phải là trường hợp thoái hóa case foo: case bar: ...), tôi đã đưa ra một nhận xét rõ ràng rằng tôi muốn sự sụp đổ xảy ra. Làm cho nó rõ ràng hơn nhiều.
Donal Fellows

3
Có như một nhận xét đơn giản // no breakthay chobreak;
Pacerier

Hoặc một [[fallthrough]]thuộc tính trong trường hợp của C ++.
Ruslan

1

Không breakcần thiết sau trường hợp cuối cùng . Tôi sử dụng từ " cuối cùng " (không phải mặc định ) vì trường hợp mặc định không cần thiết là trường hợp cuối cùng.

switch(x)
{
case 1:
//do stuff
break;

default:
//do default work
break;

case 3:
//do stuff

}

Và chúng ta biết, a break là cần thiết giữa hai cases liên tiếp . Đôi khi, tôi sử dụng if(a!=0)mã của mình để dễ đọc hơn khi người khác giới thiệu mã của tôi. Tôi có thể chọn sử dụng if(a), đó sẽ là vấn đề lựa chọn của tôi


5
Đối với tôi điều đó có nghĩa là "luôn luôn sử dụng break", chỉ trong trường hợp một số lập trình viên thêm một cái mới casevào cuối của bạn switchmà không kiểm tra xem cái đó breakcó tồn tại hay không (đó sẽ là lỗi của lập trình viên, nhưng vẫn an toàn hơn - vì mọi lý do, bởi vì bạn có thể là lập trình viên đó trong 6 tháng-)
SJuan76

@ SJuan76 Có, tôi đồng ý, an toàn tốt hơn xin lỗi, nếu bạn muốn giữ một biện pháp bảo vệ cho các lỗi trong tương lai, bạn phải bao gồm một lỗi ở cuối.
Suvarna Pattayil

1
Với lập luận đó, bạn có thể tranh luận để luôn luôn có , cuối mảng trong trường hợp giá trị mới được chèn vào. Tuy nhiên, điều đó phá vỡ một số mã và nhìn chung là xấu xí :)
Robin Castlin

1
@Robin Đặt dấu phẩy là khác nhau. Nếu nó không có ở đó và ai đó thêm một giá trị mới vào một mảng thì họ sẽ gặp lỗi biên dịch. Tuy nhiên, sẽ không có lỗi biên dịch nếu câu lệnh trường hợp trước bị thiếu dấu ngắt - vì vậy có thể lỗi này có thể bị bỏ sót và gây ra lỗi thời gian chạy.
Keith Miller

@RobinCastlin Cung cấp ngôn ngữ cho phép bạn đặt một ,. Incase, defaultđược thiết kế để trở thành trường hợp cuối cùng. Có lẽ ngôn ngữ sẽ coi breaksau đó là một lỗi. Giả sử breakđược cho phép như là một sự khác biệt CHỈ giữa hai trường hợp.
Suvarna Pattayil
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.