it-swarm-vi.com

Tôi nên sử dụng câu lệnh chuyển đổi hoặc dài nếu ... chuỗi khác?

Thông thường khi tôi nghe về câu lệnh chuyển đổi, nó sẽ tắt như một cách để thay thế lâu nếu ... chuỗi khác. Nhưng dường như khi tôi sử dụng câu lệnh chuyển đổi, tôi đang viết thêm mã mà tôi sẽ chỉ viết nếu ... khác. Bạn cũng có các vấn đề khác như giữ tất cả các biến cho tất cả các cuộc gọi trong cùng một phạm vi .

Đây là một số mã đại diện cho luồng tôi thường viết ( nhờ diam )

String comment;   // The generated insult.
int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

if (which == 0) {
    comment = "You look so much better than usual.";
} else if (which == 1) {
    comment = "Your work is up to its usual standards.";
} else if (which == 2) {
    comment = "You're quite competent for so little experience.";
} else {
    comment = "Oops -- something is wrong with this code.";
}

Sau đó, họ muốn tôi thay thế bằng cái này:

String comment;   // The generated insult.
int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

switch (which) {
    case 0:  
             comment = "You look so much better than usual.";
    break;
    case 1:  
             comment = "Your work is up to its usual standards.";
    break;
    case 2:  
             comment = "You're quite competent for so little experience.";
    break;
    default: 
             comment = "Oops -- something is wrong with this code.";
}

Có vẻ như nhiều mã hơn trong một cú pháp khó xử hơn nhiều. Nhưng có thực sự có lợi thế khi sử dụng câu lệnh switch?

36
TheLQ

Đối với tình huống cụ thể này, đối với tôi, cả ifcase đều là những lựa chọn kém. Tôi sẽ sử dụng một mảng đơn giản:

String comments[] = {
    "You look so much better than usual.",
    "Your work is up to its usual standards.",
    "You're quite competent for so little experience."
};

String comment = comments[(int)(Math.random() * 3)];

Là một lưu ý phụ, bạn thường nên tính hệ số nhân dựa trên kích thước của mảng thay vì mã hóa cứng 3.

Khi bạn sẽ sử dụng trường hợp/công tắc, sự khác biệt so với một câu lệnh if (hoặc ít nhất một sự khác biệt chính) là switch có thể bán được tự động tối ưu hóa dựa trên số lượng và mật độ của các giá trị, trong khi đó một câu lệnh if khiến trình biên dịch không có nhiều lựa chọn ngoài việc tạo mã khi bạn viết nó, kiểm tra từng giá trị cho đến khi tìm thấy giá trị khớp. Chỉ với ba trường hợp thực tế, đó không phải là vấn đề đáng lo ngại, nhưng với một số lượng đủ, nó có thể/có thể là đáng kể.

57
Jerry Coffin

Vấn đề với if...else if... chain là khi tôi đến để đọc nó, tôi phải xem xét mọi điều kiện if để hiểu chương trình đang làm gì. Ví dụ: bạn có thể có một cái gì đó như thế này:

if (a == 1) {
    // stuff
} else if (a == 2) {
    // stuff
} else if (a == 3) {
    // stuff
} else if (b == 1) {
    // stuff
} else if (b == 2) {
    // stuff
}

(rõ ràng, đối với một số lượng nhỏ các tuyên bố như thế này, nó không quá tệ)

Tôi không có cách nào để biết rằng bạn đã thay đổi điều kiện nửa chừng mà không đọc từng câu lệnh. Tuy nhiên, vì một switch chỉ giới hạn bạn trong một biến điều kiện duy nhất, tôi có thể thấy trong nháy mắt những gì đang xảy ra.

Tuy nhiên, vào cuối ngày, tôi không thích switch hoặc một chuỗi if...else if. Thường thì một giải pháp tốt hơn là một số loại bảng nhảy hoặc từ điển cho các trường hợp như trong câu hỏi ban đầu hoặc đa hình (nếu ngôn ngữ của bạn hỗ trợ điều đó). Tất nhiên, điều đó không phải lúc nào cũng có thể, nhưng tôi sẽ tìm một giải pháp tránh switch như bước đầu tiên ...

23
Dean Harding
switch (which) {
  case 0: comment = "String 1"; break;
  case 1: comment = "String 2"; break;
  case 2: comment = "String 3"; break;
  default: comment = "Oops"; break;
}

Cách viết trên của loại trường hợp chuyển đổi này là khá phổ biến. Lý do tại sao bạn cảm thấy trường hợp chuyển đổi nếu cồng kềnh là vì cơ thể bạn chỉ có một dòng và với trường hợp chuyển đổi, bạn cũng cần câu lệnh break. Vì vậy, trường hợp chuyển đổi có kích thước cơ thể gấp đôi nếu khác. Với mã quan trọng hơn, câu lệnh break sẽ không thêm nhiều vào phần thân. Đối với thân dòng đơn, việc viết mã trong cùng dòng với câu lệnh tình huống là một cách thông thường.

Như những người khác đã đề cập, một trường hợp chuyển đổi làm cho ý định rõ ràng hơn, bạn muốn đưa ra quyết định dựa trên giá trị của một biến/biểu thức duy nhất. Nhận xét của tôi hoàn toàn từ quan điểm dễ đọc và không dựa trên hiệu suất.

14
aufather

Trong trường hợp này, câu lệnh chuyển đổi phù hợp rõ ràng hơn với mục đích của mã: chọn một hành động để thực hiện dựa trên một giá trị duy nhất.

Mặt khác, các câu lệnh if khó đọc hơn nhiều - bạn phải xem tất cả chúng để chắc chắn điều gì đang xảy ra. Đối với tôi, nó ít mã hơn (ngay cả khi số lượng ký tự có thể cao hơn một chút) vì có ít phân tích về mặt tinh thần.

8
FinnNk

Tôi đồng ý với Jerry rằng một chuỗi các chuỗi tốt hơn cho trường hợp cụ thể này, nhưng nói chung, tốt hơn là sử dụng câu lệnh chuyển đổi/trường hợp hơn là một chuỗi các chuỗi khác. Nó dễ đọc hơn và đôi khi trình biên dịch có thể thực hiện tốt hơn việc tối ưu hóa theo cách đó, nhưng cũng có một lợi ích khác: đó là một cách dễ dàng hơn để gỡ lỗi.

Khi bạn nhấn công tắc đó, bạn chỉ phải bước một lần để kết thúc ở nhánh bên phải, thay vì cẩn thận bước qua vài câu lệnh một lần, và có thể nhấn phím quá nhanh và bước qua nó và thiếu một cái gì đó và có làm lại từ đầu.

8
Mason Wheeler

Tôi thích chuyển đổi trong các loại trường hợp đó, nó phù hợp hơn với điểm của mã, thực thi một câu lệnh khác nhau cho mỗi giá trị đầu vào khác nhau. Các if..else hoạt động giống như một "mẹo" để đạt được hiệu quả tương tự.

Các câu lệnh switch cũng sạch hơn, thật dễ dàng để ẩn một lỗi đánh máy trong tất cả các câu lệnh ==

Ngoài ra, đối với các khối lớn trong C, chuyển đổi nhanh hơn.

else..if có thể phù hợp hơn khi bạn có thứ gì đó như phạm vi (từ 1 đến 100, làm điều này, từ 100 đến 200 làm điều đó) hoặc trong C, khi bạn cố gắng thực hiện chuyển đổi với các thành phần như chuỗi (có thể bằng các ngôn ngữ khác ). Mà giống nhau.

Tôi có xu hướng sử dụng nhiều công tắc khi tôi lập trình trong C.

3
Khelben

Tôi thường không thích một trong hai cách tiếp cận. Chuyển đổi dài hoặc nếu các câu lệnh chỉ xin được tái cấu trúc thành một trừu tượng hướng đối tượng (tuy nhiên ví dụ của bạn tôi sẽ phân loại là ngắn, không dài).

Cá nhân tôi sẽ bọc loại mã đó vào một phương thức trợ giúp riêng.

private string GetInsult()
{
    int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

    switch (which) {
        case 0: return "You look so much better than usual.";
        case 1: return "Your work is up to its usual standards.";
        case 2: return "You're quite competent for so little experience.";
        default: return "Oops -- something is wrong with this code.";
    }
}

public void Foo()
{
    string comment = GetInsult();
    Print(comment);
}

Đặt công tắc trong một phương thức riêng biệt cho phép bạn đặt các câu lệnh trả lại trực tiếp bên trong câu lệnh chuyển đổi (ít nhất là trong c #), loại bỏ sự cần thiết của các câu lệnh ngắt, làm cho mã dễ đọc hơn nhiều.

Và điều này là imho đẹp hơn nhiều so với if/other if/other if tiếp cận.

2
Pete

Chọn một cái gì đó hiệu quả, ngắn gọn, và sau đó tài liệ không chỉ những gì bạn đã làm, mà tại sao.

Mã có thể được xem lại, và không phải lúc nào cũng bởi tác giả ban đầu của nó.

Đôi khi bạn có thể cố tình chọn một triển khai trên một bạn đang nghĩ về mã không tồn tại.

2
Walt Stoneburner

Một trong những điều làm cho kiểu C/C # switch đặc biệt khó chịu là sự khăng khăng về giá trị case là bằng chữ. Một điều thú vị về VB/VB.NET là select/case cho phép mỗi trường hợp là bất kỳ biểu thức boolean nào. Đó là thuận tiện. Trong chừng mực, một loạt các biểu thức boolean loại trừ lẫn nhau thường rất hữu ích, một loạt các if/khác ifs linh hoạt hơn, chưa kể đến việc gõ và đọc hiệu quả hơn.

0
Joel Brown

Trong python, không có câu lệnh chuyển đổi, bởi vì if/Elif/other là Nice:

a = 5

if a==1:
    print "do this"
Elif a == 2:
    print "do that"
Elif a == 3:
    print "do the other"
Elif 3 < a < 9:
    print "do more"
Elif 9 <= a < 15:
    print "do nothing"
else:
    print "say sorry"

Đơn giản phải không?

0
Christopher Mahan