Sử dụng hợp lý các báo cáo chuyển đổi thông qua


14

Khi nào thì thích hợp để sử dụng câu lệnh chuyển đổi rơi (cổ điển)? Việc sử dụng như vậy có được khuyến khích và khuyến khích hay nên tránh bằng mọi giá?


Không phải tất cả các ngôn ngữ đều cho phép thông qua các câu lệnh chuyển đổi.
Oded

@Oded, chỉnh sửa, thêm từ "cổ điển". Không phải tất cả các ngôn ngữ đều cho phép vượt qua, tuy nhiên tôi khẳng định đó là cổ điển)
shabunc

3
Nếu bạn đang nói về thiết bị của Duff , đó là một điều.
Oded

6
@Oded: Đó là điều đầu tiên mà hầu hết mọi người nghĩ đến, nhưng điều đó hầu như không "phù hợp". Theo đó , chính Duff đã nói "Điều này chắc chắn cung cấp một cuộc tranh luận trong cuộc thảo luận về việc liệu công tắc có nên vượt qua theo mặc định hay không, nhưng tôi không chắc liệu cuộc tranh luận đó có đúng hay không."
BlueRaja - Daniel Pflughoeft

Câu trả lời:


15

Đây là một ví dụ nơi nó sẽ hữu ích.

public Collection<LogItems> GetAllLogItems(Level level) {
    Collection<LogItems> result = new Collection<LogItems>();
    switch (level) {
        // Note: fall through here is INTENTIONAL
        case All:
        case Info:
             result.Add(GetItemsForLevel(Info));
        case Warning:
             result.Add(GetItemsForLevel(Warning));
        case Error:
             result.Add(GetItemsForLevel(Error));
        case Critical:
             result.Add(GetItemsForLevel(Critical));
        case None:
    }
    return result;
}

Loại điều này (trong đó một trường hợp bao gồm trường hợp khác) là khá hiếm, tôi nghĩ, đó là lý do tại sao một số ngôn ngữ mới hơn không cho phép chuyển đổi hoặc yêu cầu cú pháp đặc biệt cho nó.


13
Ví dụ này, trong khi thú vị, đang thiếu // INTENTIONAL FALL THROUGH HEREbình luận tất cả các mũ cần thiết .
Russell Borogove

Thật dễ dàng để viết mã này bằng cách thực hiện bằng cách thực hiện GetItemsForLevel(Info)cuộc gọi GetItemsForLevel(Warning)và cứ thế.
Caleb

@RussellBorogove: Hoàn toàn chính xác.
cấu hình

@Caleb: Trong trường hợp này, vâng. Nhưng nếu các cuộc gọi phức tạp hơn một chút thì sao? Nó có thể có một chút lông, trong khi rơi qua làm cho nó có vẻ đơn giản. Tôi nên lưu ý rằng tôi không thực sự ủng hộ việc sử dụng thông qua - tôi chỉ nói rằng nó có thể hữu ích trong một số tình huống.
cấu hình

Không phải là ví dụ tốt nhất. Có một trật tự của các cấp cảnh báo. Bằng cách xác định thứ tự đó, phương thức này giảm xuống một dòng các mục lọc mã khi mức mục ít nhất bằng với mức mong muốn.
kevin cline

8

Tôi sử dụng chúng khi chức năng nhất định phải được áp dụng cho nhiều hơn một giá trị. Ví dụ: giả sử bạn có một đối tượng có thuộc tính được gọi là operCode. Nếu mã bằng 1, 2, 3 hoặc 4, bạn muốn startOperationX (). Nếu là 5 hoặc 6, bạn muốn startOperationY () và 7 bạn startOperationZ (). Tại sao có 7 trường hợp hoàn chỉnh với chức năng và nghỉ khi bạn có thể sử dụng thông qua?

Tôi nghĩ rằng nó hoàn toàn hợp lệ trong một số trường hợp nhất định, đặc biệt là nếu nó tránh được 100 câu lệnh if-other. =)


4
Những gì bạn đang mô tả là một switchvới nhiều cases được gắn vào cùng một mã. Điều đó khác với một lần rơi, trong đó việc xử tử người này casetiếp tục vào vụ tiếp theo vì thiếu một người breakgiữa họ.
Blrfl

3
Nó không thực sự quan trọng, sự sụp đổ chỉ là thiếu một tuyên bố phá vỡ để nó "rơi vào" trường hợp tiếp theo.
Yatrix

Tôi sẽ diễn đạt lại kịch bản trong câu trả lời của bạn để phản ánh điều đó.
Blrfl

2
@Yatrix: Tôi không đồng ý. Điều khác biệt là có nhiều trường hợp liên tiếp thực hiện cùng một khối mã chính xác hơn là bỏ qua một dấu ngắt. Một là thông lệ, cái khác cách xa nó (ime) - và khả năng đọc sai và luồng kiểm soát ngoài ý muốn là lớn hơn nhiều.
quentin-starin

3
@qes vâng, nó khác nhau, nhưng cả hai đều là điểm rơi. Anh ấy hỏi khi nào / nếu nó phù hợp. Tôi đã đưa ra một ví dụ về khi nó sẽ. Nó không có nghĩa là một ví dụ bao gồm tất cả. Tùy thuộc vào ngôn ngữ, có các tuyên bố trước khi thông qua có thể không hoạt động. Tôi không nghĩ nó sẽ như vậy với C # stackoverflow.com/questions/174155/ từ
Yatrix

8

Thỉnh thoảng tôi đã sử dụng chúng, tôi nghĩ cách sử dụng luôn phù hợp - nhưng chỉ khi được kèm theo bình luận thích hợp.


7

Trường hợp rơi qua là hoàn toàn tốt đẹp. Tôi thường thấy rằng một phép liệt kê được sử dụng ở nhiều nơi và khi bạn không cần phân biệt một số trường hợp thì việc sử dụng logic rơi sẽ dễ dàng hơn.

Ví dụ (lưu ý các ý kiến ​​giải thích):

public boolean isAvailable(Server server, HealthStatus health) {
  switch(health) {
    // Equivalent positive cases
    case HEALTHY:
    case UNDER_LOAD:
      return true;

    // Equivalent negative cases
    case FAULT_REPORTED:
    case UNKNOWN:
    case CANNOT_COMMUNICATE:
      return false;

    // Unknown enumeration!
    default:
      LOG.warn("Unknown enumeration " + health);
      return false;
  }
}

Tôi thấy loại sử dụng này hoàn toàn chấp nhận được.


Lưu ý rằng có một sự khác biệt lớn giữa case X: case Y: doSomething()case X: doSomething(); case Y: doAnotherThing(). Trong lần đầu tiên, ý định là khá rõ ràng, trong khi trong lần thứ hai, sự rơi qua có thể có chủ ý hoặc không. Theo kinh nghiệm của tôi, ví dụ đầu tiên không bao giờ kích hoạt bất kỳ cảnh báo nào trong trình biên dịch / trình phân tích mã, trong khi ví dụ thứ hai thì không. Cá nhân, tôi sẽ chỉ gọi ví dụ thứ hai là "rơi qua" - mặc dù không chắc chắn về một định nghĩa "chính thức".
Jens Bannmann

6

Nó phụ thuộc vào:

  • sở thích cá nhân của bạn
  • tiêu chuẩn mã hóa của chủ nhân
  • số lượng rủi ro liên quan

Hai vấn đề chính liên quan đến việc để một trường hợp rơi vào trường hợp tiếp theo là:

  1. Nó làm cho mã của bạn phụ thuộc vào thứ tự của các báo cáo trường hợp. Đó không phải là trường hợp nếu bạn không bao giờ rơi vào, và nó thêm một mức độ phức tạp thường không được chào đón.

  2. Không rõ ràng rằng mã cho một trường hợp bao gồm mã cho một hoặc nhiều trường hợp tiếp theo.

Một số nơi rõ ràng cấm rơi qua. Nếu bạn không làm việc ở một nơi như vậy, và nếu bạn cảm thấy thoải mái với việc luyện tập và nếu việc phá mã trong câu hỏi sẽ không gây ra bất kỳ đau khổ thực sự nào, thì đó có thể không phải là điều tồi tệ nhất trên thế giới. Tuy nhiên, nếu bạn làm điều đó, hãy chắc chắn để đưa ra một nhận xét thu hút sự chú ý gần đó để cảnh báo những người đến sau (bao gồm cả tương lai bạn).


4

Đây là một ví dụ nhanh chóng (không được thừa nhận (không xử lý đặc biệt năm nhuận)) về việc rơi vào làm cho cuộc sống của tôi đơn giản hơn:

function get_julian_day (date) {
    int utc_date = date.getUTCDate();
    int utc_month = date.getUTCMonth();

    int julian_day = 0;

    switch (utc_month) {
        case 11: julian_day += 30;
        case 10: julian_day += 31;
        case 9:  julian_day += 30;
        case 8:  julian_day += 31;
        case 7:  julian_day += 31;
        case 6:  julian_day += 30;
        case 5:  julian_day += 31;
        case 4:  julian_day += 30;
        case 3:  julian_day += 31;
        case 2:  julian_day += 28;
        case 1:  julian_day += 31;
        default: break;
    }

    return julian_day + utc_date;
}

5
Mặc dù điều này là thông minh, nhưng thời gian bạn tiết kiệm được từ việc này sẽ vượt xa thời gian để người khác tìm ra điều này làm gì. Ngoài ra, bạn có thể có hiệu suất tốt hơn bằng cách loại bỏ khía cạnh rơi xuống, tức là 31 + 28 + 31 luôn là 90. Nếu bạn sẽ làm điều này, bạn cũng có thể chỉ cần đặt tổng số trong các trường hợp vì chỉ có 11 để xem xét.
JimmyJames

Bạn nói đúng, ví dụ của tôi chắc chắn là có khả năng :) Tôi sẽ nói, tuy nhiên, sẽ dễ dàng phát hiện ra một lỗi ẩn hơn khi số ngày được đánh vần như thế này thay vì tính toán trước tất cả các ngày tích lũy cho mỗi trường hợp của công tắc .
AaronDanielson

2
Tôi sẽ cấp cho bạn điều đó nhưng làm điều đó trong một tuyên bố liên tục sẽ tốt hơn, ví dụ: FEB_START = 31; MAR_START = FEB_START + 28; vv không chắc ngôn ngữ này là gì nhưng trong nhiều, nó sẽ được tính vào thời gian biên dịch. Vấn đề lớn hơn ở đây là nó hơi khó hiểu. Không nhiều đến mức đó là một ý tưởng tồi, chỉ là không điển hình. Trừ khi có một lợi ích thực sự lớn, nói chung là tốt hơn để gắn bó với các thành ngữ phổ biến.
JimmyJames

1
Thay thế tuyệt vời, sử dụng hằng số cho ngày bắt đầu trong ví dụ này. Dù sao, vấn đề ở đây là một khoản tiền tích lũy là một cách sử dụng tuyệt vời cho trường hợp chuyển đổi trường hợp chuyển đổi. Tôi đồng ý 100% về việc sử dụng các thành ngữ phổ biến, nhưng bản chất của câu hỏi này là mạo hiểm vào các tính năng bí truyền hơn, nơi các thành ngữ phổ biến khó có thể xuất hiện.
AaronDanielson

3

Nếu tôi cảm thấy cần phải đi từ trường hợp này sang trường hợp khác (hiếm, phải thừa nhận), tôi thích phải rất rõ ràng và goto casetất nhiên, điều đó giả định rằng ngôn ngữ của bạn hỗ trợ nó.

Bởi vì thông thường rất hiếm và rất dễ bị bỏ qua khi đọc mã, tôi cảm thấy nó phù hợp để rõ ràng - và một chiếc goto, ngay cả khi nó là một trường hợp, nên nổi bật như ngón tay cái đau.

Nó cũng giúp tránh các lỗi có thể xảy ra khi các báo cáo trường hợp được sắp xếp lại.

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.