Geçiş anahtarı ifadelerinin uygun kullanımları


14

Bir düşme (klasik) anahtar deyimi ne zaman kullanılmalı? Bu tür bir kullanım tavsiye edilir ve teşvik edilir mi, ne pahasına olursa olsun kaçınılmalıdır mı?


Tüm diller anahtar ifadelerinde düşüşe izin vermez.
Oded

@Oded, düzenlendi, "klasik" sözcük eklendi. Tüm diller düşmesine izin vermiyor, yine de klasik olduğu konusunda ısrar ediyorum)
shabunc

3
Duffs'ın cihazı hakkında konuşuyorsanız , bu bir şeydir.
Oded

6
@Oded: Çoğu insanın ilk düşündüğü şey bu, ancak bu pek de uygun değil. Göre bu , Duff kendisi söyledi "Bu kesinlikle anahtar varsayılan olarak suya düşmek gerekip gerekmediğini tartışmada bir tartışma sağlar, ancak argüman için veya buna karşı olup olmadığından emin değilim."
BlueRaja - Dany Pflughoeft

Yanıtlar:


15

İşte yararlı olacağı bir örnek.

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

Bu tür bir şey (bir vaka diğerini içerir) oldukça nadir, bence, bu yüzden bazı yeni diller ya fallover'a izin vermiyor ya da bunun için özel sözdizimi gerektirmiyor.


13
Bu örnek, ilginç olsa da, gerekli olan tüm büyük harf // INTENTIONAL FALL THROUGH HEREyorumundan yoksundur .
Russell Borogove

Bu kodu GetItemsForLevel(Info)çağrıyı çağırarak GetItemsForLevel(Warning)vb.
Caleb

@RussellBorogove: Kesinlikle doğru.
yapılandırıcı

@Caleb: Bu durumda, evet. Peki ya çağrılar biraz daha karmaşık olsaydı? Biraz tüylü olabilir, düşerken basit görünmesini sağlar. Aslında düşmeyi kullanmaktan yana olmadığımı not etmeliyim - sadece belirli durumlarda yararlı olabileceğini söylüyorum.
yapılandırıcı

En iyi örnek değil. Uyarı seviyelerinin sıralaması vardır. Bu siparişi tanımlayarak, öğe seviyesi en az istenen seviyeye eşit olduğunda, bu yöntem tek bir kod filtreleme öğesi satırına düşer.
kevin cline

8

Bazı işlevlerin birden fazla değer için uygulanması gerektiğinde bunları kullanıyorum. Örneğin, operasyonKodu adlı bir özelliğe sahip bir nesneniz olduğunu varsayalım. Kod 1, 2, 3 veya 4'e eşitse, startOperationX () işlevini başlatmak istersiniz. 5 veya 6 ise, StartOperationY () 'yi ve 7' yi StartOperationZ () 'ı istiyorsunuz. Düşüşleri kullanabilmeniz için neden 7 tam işlevsellik ve kırılma vakası var?

Özellikle 100 if-else ifadesinden kaçınırsa, bazı durumlarda tamamen geçerli olduğunu düşünüyorum. =)


4
Açıkladığınız, aynı koda bağlı switchbirden fazla cases olan bir. Bu, aralarında casebir eksiklik nedeniyle birinin yürütülmesinin bir sonrakine devam ettiği bir düşüşten farklıdır break.
Blrfl

3
Gerçekten önemli değil, düşüş sadece bir break ifadesinin olmamasıdır, bu yüzden bir sonraki davaya "düşer".
Yatrix

Cevabınızdaki senaryoyu bunu yansıtacak şekilde yeniden ifade ederim.
Blrfl

2
@Yatrix: Kabul etmiyorum. Birbirini izleyen vakaların hepsinin, aynı kod bloğunu yürütmesini bir mola atmaktan çok daha farklıdır. Biri rutin, diğeri ondan uzak (ime) - ve yanlış okuma ve istenmeyen kontrol akışı potansiyeli çok daha fazla.
quentin-starin

3
@ qes evet, bu farklı, ama ikisi de düşüşler. Ne zaman uygun olup olmayacağını sordu. Ne zaman olacağına dair bir örnek verdim. Her şey dahil bir örnek olması amaçlanmamıştı. Dile bağlı olarak, düşmeden önce ifadeler almak işe yaramayabilir. C # ile olacağını sanmıyorum stackoverflow.com/questions/174155/…
Yatrix

8

Onları zaman zaman kullandım, bence her zaman uygun kullanımı - ama sadece uygun yoruma dahil edildiğinde.


7

Düşen kılıflar gayet iyi. Çoğu zaman bir numaralandırmanın birçok yerde kullanıldığını ve bazı durumları ayırt etmeniz gerekmediğinde düşme mantığını kullanmanın daha kolay olduğunu görüyorum.

Örneğin (açıklayıcı yorumlara dikkat edin):

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

Bu tür kullanımları mükemmel kabul edilebilir buluyorum.


case X: case Y: doSomething()Ve arasında büyük bir fark olduğunu unutmayın case X: doSomething(); case Y: doAnotherThing(). Birincisinde, niyet oldukça açıkken, ikincisinde düşme kasıtlı olabilir veya olmayabilir. Deneyimlerime göre, ilk örnek derleyiciler / kod analizörlerinde hiçbir zaman ikinciyi tetiklemez. Şahsen, sadece ikinci örneği "düşmek" olarak adlandırırdım - yine de "resmi" bir tanımdan emin değilim.
Jens Bannmann

6

Göre değişir:

  • kişisel tercihin
  • işvereninizin kodlama standartları
  • içerdiği risk miktarı

Bir davanın diğerine düşmesine neden olan iki ana sorun şunlardır:

  1. Kodunuzu vaka ifadelerinin sırasına bağlı hale getirir. Hiç düşmezseniz durum böyle değildir ve genellikle hoş karşılanmayan bir karmaşıklık derecesi ekler.

  2. Bir vakanın kodunun, sonraki bir veya daha fazla vakanın kodunu içerdiği açık değildir.

Bazı yerler açıkça düşmeyi yasaklar. Böyle bir yerde çalışmazsanız ve uygulamadan memnunsanız ve söz konusu kodu kırmak herhangi bir gerçek acıya neden olmazsa, o zaman dünyadaki en kötü şey olmayabilir. Bunu yaparsanız, daha sonra gelenleri uyarmak için yakınlarda dikkat çekici bir yorum koyduğunuzdan emin olun (gelecek dahil).


4

İşte hayatımı kolaylaştırmak için hızlı (kuşkusuz eksik (artık yıl özel işlem yok)) düşme örneği:

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
Bu bir tür zeki olsa da, bunu yapmaktan kazandığınız zaman, diğer insanların bunun ne yaptığını anlaması için çok daha ağır basacaktır. Ayrıca, düşme yönünü kaldırarak daha iyi performans elde edebilirsiniz, yani 31 + 28 + 31 her zaman 90'dır. Bunu yapacaksanız, dikkate alınması gereken sadece 11 tane olduğundan, toplamları vakalara koyabilirsiniz.
JimmyJames

Haklısın, benim örneğim kesinlikle uyduruldu :) Bununla birlikte, anahtarın her vakası için tüm kümülatif günleri önceden hesaplamak yerine, gün sayısı bu şekilde yazıldığında gizli bir hatayı tespit etmek daha kolay .
AaronDanielson

2
Size bunu söyleyeceğim, ancak bunu sürekli bir bildirimle yapmak tercih edilebilir, örneğin FEB_START = 31; MAR_START = FEB_START + 28; vb. bu dilin ne olduğundan emin değil ama çoğunda derleme anında hesaplanacaktır Buradaki en büyük sorun biraz geniş olması. O kadar da kötü bir fikir değil, sadece atipik. Gerçekten büyük bir fayda olmadıkça, genel deyimlere bağlı kalmak genellikle daha iyidir.
JimmyJames

1
Bu örnekte başlangıç ​​günleri için sabitler kullanarak mükemmel bir alternatif. Her neyse, buradaki nokta, kümülatif bir toplamın bir anahtar-kasa düşmesi için harika bir kullanım olduğudur. Ortak deyimleri kullanma konusunda% 100 katılıyorum, ancak bu sorunun doğası, ortak deyimlerin gelmesinin zor olduğu daha ezoterik özelliklere giriyor.
AaronDanielson

3

Bir vakadan diğerine gitme ihtiyacı hissedersem (nadiren, kuşkusuz), çok açık olmayı tercih ederim ve goto caseelbette, dilinizin bunu desteklediğini varsayar.

Kodlama sırasında düşmek çok nadir ve göz ardı etmek çok kolay olduğu için, açık olmanın uygun olduğunu hissediyorum - ve bir durumda olsa bile bir goto, ağrılı bir başparmak gibi göze çarpmalıdır.

Ayrıca vaka ifadeleri yeniden sıralandığında oluşabilecek hataların önlenmesine yardımcı olur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.