2010-06-24 28 views
82

Khi tôi tạo ra một tuyên bố switch trong VS2008 C# như thế này (giả tạo):Tại sao C# bị ngắt nếu không tùy chọn?

switch (state) { 
    case '1': 
     state = '2'; 
    case '2': 
     state = '1'; 
} 

nó than phiền rằng tôi không được phép hủy thông qua:

kiểm soát không thể lọt qua từ một trường hợp nhãn ('trường hợp' 1 '(0x31):') sang một số khác

Nếu bạn không được phép bỏ qua, thì mục đích của câu lệnh break là gì? Tại sao các nhà thiết kế ngôn ngữ lại không bỏ qua nó và tự động nhảy đến cuối câu lệnh switch thay vì buộc chúng tôi phải đặt một cấu trúc không cần thiết?

Trả lời

68

Từ miệng ngựa (MSDN) Why is the C# switch statement designed to not allow fall-through, but still require a break?.

Trích dẫn các bit nổi bật, đây là lý do tại sao họ không cho phép sụp đổ qua:

hành vi mùa thu qua ngầm này thường được sử dụng để giảm số lượng mã cần thiết và thường không phải là một vấn đề lần đầu tiên mã được viết. Tuy nhiên, khi mã chuyển từ giai đoạn phát triển ban đầu sang giai đoạn bảo trì, mã ở trên có thể dẫn đến các lỗi tinh vi rất khó gỡ lỗi. Các lỗi này là do lỗi rất phổ biến của nhà phát triển khi thêm một trường hợp, nhưng vẫn quên đặt dấu ngắt ở cuối khối.

Trong C#, câu lệnh chuyển đổi yêu cầu điều khiển luồng rõ ràng xảy ra ở cuối của một trường hợp, hoặc là ngắt, goto, trả lại hoặc ném. Nếu nhà phát triển mong muốn các ngữ nghĩa thu gọn, nó có thể đạt được bằng một goto rõ ràng ở cuối câu lệnh case.

Và đây là lý do tại sao nó không tự động:

Theo kết quả của các quy tắc C# đòi hỏi rõ ràng dòng chảy kiểm soát xảy ra ở phần cuối của một khối trường hợp (thường là hầu hết nghỉ ngơi), nhiều người câu hỏi tại sao hành vi đơn giản là không thay đổi như vậy mà sự sụp đổ đã không xảy ra. Đó là, không làm cho phá vỡ cần thiết, chỉ cần thay đổi ngữ nghĩa của chuyển đổi để không có mùa thu cho các trường hợp. Lý do này không được thực hiện để các nhà phát triển đã rất quen với C++ sẽ không có một thời gian khó hiểu những gì một tuyên bố chuyển đổi đang làm.

+0

Liên kết không còn hoạt động nữa. –

+1

http://web.archive.org/web/20110515005800/http://msdn.microsoft.com/en-us/vcsharp/aa336815.aspx –

+3

Và bây giờ, 7 giọt nước mắt sau khi được viết, chúng tôi thấy quyết định này câm như thế nào là. Bây giờ chúng tôi đang giới thiệu mô hình phù hợp, một khái niệm mới nóng mà họ quyết định co-opt 'chuyển đổi 'cú pháp cho và bây giờ là bogged xuống bởi một quyết định được thực hiện để" không nhầm lẫn lập trình c + + 2 thập kỷ trước ". Không phải là lựa chọn tốt nhất, C# team. –

12

Nếu bạn không có bất kỳ mã trong trường hợp 1, bạn được phép lọt qua, vì vậy bạn có thể nói rằng "tất cả các trường hợp này chia sẻ đoạn mã này"

+0

Nhưng trong trường hợp đó, bạn sẽ không nhận được cảnh báo. Trình biên dịch cảnh báo bạn về một cái gì đó nó có thể suy ra. – Kobi

79

Về cơ bản để làm cho nó quen thuộc hơn với C/C++/nhà phát triển Java. Cá nhân tôi nghĩ đó là một sai lầm, nhưng đó là lý do.

tôi có vẻ rất muốn một khối buộc:

case '1': 
{ 
} 

Bên cạnh bất cứ điều gì khác, mà có thể đã tránh được những tình huống Phạm vi biến lạ cho chuyển/trường hợp. Bạn vẫn có thể có nhiều nhãn trường hợp, tất nhiên:

case '0': 
case '1': 
{ 
} 

Nó cũng có thể được tốt đẹp để có thể liệt kê nhiều trường hợp đơn giản hơn:

case '0', '1': 
{ 
} 

Oh, và một chút nit-pick về bạn mô tả ngôn ngữ hiện tại: bạn không để nghỉ ngơi. Nó chỉ là kết thúc của vụ án phải được unreachable. Bạn cũng có thể có throw, goto hoặc return. Có thể có những người khác mà tôi đã bỏ lỡ, quá :)

+2

@Jon +1 - Không bao giờ biết bạn có thể làm điều đó! – GenericTypeTea

+0

@GenericTypeTea: bit nào? –

+0

Tôi nghĩ rằng đó là một quyết định tốt để không làm cho các cấu trúc giống hệt nhau hoạt động khác nhau. Đó sẽ là một địa ngục cho các lập trình viên phải chuyển đổi ngôn ngữ thường xuyên. –

35

Bạn được phép thả qua, nhưng bạn phải làm như vậy một cách rõ ràng với goto keyword:

switch (state) { 
    case '1': 
     state = '2'; 
     goto case '2'; 
    case '2': 
     state = '1'; 
     break; 
} 

Bạn có thể break hoặc goto trong C#, nhưng những gì bạn không thể làm không phải là trạng thái mà bạn muốn, bởi vì đó là một nguồn tiềm năng của các lỗi khó tìm.

Sẽ dễ dàng hơn khi nhận thấy mã của bạn cho biết goto khi bạn muốn break (hoặc ngược lại) so với khi bạn quên thêm.

Nghe có vẻ ngu ngốc, nhưng nhiều tìm kiếm mệt mỏi trong hai giờ vì nguyên nhân gây ra lỗi C++ kết thúc trong việc nhận ra đột ngột rằng bạn quên thêm break và mã của bạn luôn rơi. C# tránh điều đó bằng cách buộc bạn phải nêu rõ bạn muốn gì.

+2

Tôi xấu hổ vì tôi không biết bạn có thể 'tiếp tục'.Chỉ cần nghĩ rằng nó là bất hợp pháp để tránh tất cả rơi qua lỗi ... Cảm ơn :) – simendsjo

+3

Bạn đã thử mã này? Nó không biên dịch. Bạn có thể làm "goto case '2'". –

+0

Cung cấp cho tôi "Không có vòng lặp kèm theo để ngắt hoặc tiếp tục" –

Các vấn đề liên quan