it-swarm.dev

Anahtar deyimlerini mi yoksa uzun ... zincirleri mi kullanmalıyım?

Çoğunlukla switch ifadesini duyduğumda, uzun zincirleri değiştirmek için bir yol olarak ertelendi ... başka zincirler. Ama öyle görünüyor ki switch deyimini kullandığımda, eğer sadece ... başka yazacağım daha fazla kod yazıyorum. Ayrıca tüm aramalar için tüm değişkenleri aynı kapsamda tutmak gibi başka sorunlarınız da var.

İşte normalde yazdığım akışı temsil eden bazı kodlar ( diam sayesinde )

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

Sonra bunu bununla değiştirmemi istiyorlar:

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

Çok daha garip bir sözdiziminde çok daha fazla kod gibi görünüyor. Ancak switch deyimini kullanmanın gerçekten bir avantajı var mı?

36
TheLQ

Bu özel durum için, hem if hem de case'nin kötü seçimler olduğu anlaşılıyor. Basit bir dizi kullanırdım:

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)];

Yan not olarak, çarpanı genellikle 3 Kodlamasını yapmak yerine dizinin boyutuna göre hesaplamanız gerekir.

Ne zaman olur bir vaka/anahtar kullandığınıza gelince, if deyiminden (veya en az bir büyük farktan) oluşan bir basamaktan farkı switch yarı- değerlerin sayısına ve yoğunluğuna göre otomatik olarak optimize edilirken, if ifadelerinden oluşan bir basamaklı derleyiciyi çok az seçenekle bırakır, ancak yazdığınız gibi kod oluşturmak için bir eşleşme bulana kadar bir değeri test eder. Sadece üç gerçek durumla, bu neredeyse bir endişe kaynağı değildir, ancak yeterli sayıda olması önemli olabilir/olabilir.

57
Jerry Coffin

if...else if... Zinciri ile ilgili sorun, onu okumak için geldiğimde, programın ne yaptığını anlamak için her if durumuna bakmak zorunda olmasıdır. Örneğin, böyle bir şeye sahip olabilirsiniz:

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

(açıkçası, bunun gibi az sayıda ifade için, o kadar da kötü değil)

Her bir ifadeyi okumadan koşul değişkenini yarıya kadar değiştirdiğinizi bilmenin hiçbir yolu olmazdı. Ancak, bir switch sizi yalnızca tek bir koşul değişkeni ile sınırladığı için neler olduğunu bir bakışta görebilirim.

Ancak günün sonunda ne switch ne de if...else if Zincirini tercih ederim. Genellikle daha iyi bir çözüm, orijinal soru veya polimorfizm gibi durumlar için bir çeşit atlama tablosu veya sözlüktür (diliniz bunu destekliyorsa). Tabii ki her zaman mümkün değildir, ancak ilk adım olarak switch 'ı önleyen bir çözüm ararım ...

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

Bu tip anahtar kutusu yazmanın yukarıdaki yolu oldukça yaygındır. Bulkier ise anahtar kasasını hissetmenizin nedeni, vücudunuzun sadece bir satır olması ve bir anahtar kasasıyla da mola ifadesine ihtiyacınız vardı. Yani anahtar kasası, eğer başka bir boyda iki kat daha büyüktü. Daha önemli bir kodla, break ifadesi gövdeye fazla bir şey eklemez. Tek satırlı gövde için, kodu vaka ifadesiyle aynı satıra yazmak yaygın bir uygulamadır.

Diğerlerinin daha önce de belirttiği gibi, bir anahtar durum amacı daha açık hale getirir, tek bir değişkenin/ifadenin değerine dayalı bir karar vermek istersiniz. Yorumlarım performansa göre değil, sadece okunabilirlik açısından.

14
aufather

Bu durumda, switch ifadesi kodun amacıyla daha açık bir şekilde eşleşir: tek bir değere dayalı olarak gerçekleştirilecek bir eylem seçin.

Öte yandan if ifadelerini okumak çok daha zordur - neler olup bittiğinden emin olmak için hepsine bakmanız gerekir. Zihinsel olarak ayrıştırmak için daha az olduğu için bana göre daha az kod (karakter sayısı belki biraz daha yüksek olsa bile).

8
FinnNk

Jerry ile bu özel durum için bir dizi dizinin daha iyi olduğunu kabul ediyorum, ancak genel olarak bir elseifs zincirinden ziyade bir switch/case deyimi kullanmak daha iyidir. Okuması daha kolay ve bazen derleyici bu şekilde optimize etmek için daha iyi bir iş yapabilir, ancak başka bir avantajı daha var: hata ayıklamak çok daha kolay.

Bu anahtara bastığınızda, bir kerede birden fazla if ifadesini dikkatlice atmak ve muhtemelen anahtara çok hızlı bir şekilde basmak ve onu geçmek, bir şeyleri kaçırmak ve baştan başlamak.

8
Mason Wheeler

Ben bu tür durumlarda geçiş tercih, kod noktası çok daha iyi eşleşir, her farklı giriş değeri için farklı bir ifade yürütmek. if..else aynı etkiyi elde etmek için daha çok bir "hile" gibi davranır.

switch ifadeleri de daha temiz, yazım hatalarının hepsinde gizli olması kolaydır ==

Ayrıca, C'deki büyük bloklar için anahtar daha hızlıdır.

else..if, aralık gibi bir şeye sahip olduğunuzda (1 ile 100 arasında, bunu yapın, 100 ile 200 arasında) veya C'de dizeler gibi öğelerle geçiş yapmaya çalıştığınızda (diğer dillerde mümkündür) daha uygun olabilir ). Bu da aynı.

C programladığımda çok fazla anahtar kullanma eğilimindeyim.

3
Khelben

Genellikle her iki yaklaşımı da sevmem. Uzun anahtar veya ifadeler sadece nesne yönelimli bir soyutlamaya yeniden uyarılmaya yalvarırsa (ancak örneğiniz uzun değil kısa olarak sınıflandırırım).

Şahsen bu tür bir kodu ayrı bir yardımcı yöntemle sararım.

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

Anahtarı ayrı bir yöntemle yerleştirmek, dönüş deyimlerini doğrudan switch deyiminin içine yerleştirmenize (en azından c # olarak) izin vererek break ifadeleri ihtiyacını ortadan kaldırarak kodu daha kolay okunur hale getirir.

Ve bu, if/else if/else if yaklaşımından çok daha hoştur.

2
Pete

Verimli, kısa ve sonra belge yalnızca yaptığınız şeyi değil, nedenini seçin.

Kod her zaman orijinal yazarı tarafından değil, yeniden gözden geçirilebilir.

Bir uygulamayı diğerine göre kasıtlı olarak seçebileceğiniz zamanlar vardır çünkü mevcut olmayan kod hakkında ileri görüşlüsünüz.

2

C/C # stilini switch özellikle can sıkıcı yapan şeylerden biri, case değerinin değişmez olma ısrarıdır. VB/VB.NET hakkında güzel bir şey select/case her durumun herhangi bir boole ifadesi olmasına izin verir. B uygundur. Karşılıklı olarak ayrıcalıklı boole ifadeleri dizisi olarak genellikle yararlıdır, bir dizi if/else daha esnektir, yazmak ve okumak için daha verimli olduğundan bahsetmiyoruz.

0
Joel Brown

Python'da anahtar ifadesi yoktur, çünkü/Elif/else Nice ise:

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"

Basit değil mi?

0