Anahtar ifadeleri her zaman varsayılan bir cümle içermeli mi?


255

İlk kod incelemelerimden birinde (bir süre önce), tüm anahtar ifadelerinde varsayılan bir cümle eklemenin iyi bir uygulama olduğu söylendi. Son zamanlarda bu tavsiyeyi hatırladım ama gerekçesinin ne olduğunu hatırlayamıyorum. Şimdi bana oldukça garip geliyor.

  1. Her zaman varsayılan bir ifade eklemenin mantıklı bir nedeni var mı?

  2. Bu dil bağımlı mı? O sırada hangi dili kullandığımı hatırlamıyorum - belki bu bazı diller için geçerlidir, diğerleri için geçerli değildir?


9
Büyük ölçüde dile bağlı olacak
skaffman

Yanıtlar:


278

Anahtar kutuları neredeyse her zaman bir defaultdavaya sahip olmalıdır .

Kullanmak için nedenler default

Beklenmeyen bir değeri 'yakalamak'

switch(type)
{
    case 1:
        //something
    case 2:
        //something else
    default:
        // unknown type! based on the language,
        // there should probably be some error-handling
        // here, maybe an exception
}

2. Vakaların özel davranış için olduğu 'varsayılan' eylemleri işlemek.

Bu, menü odaklı programlarda ve bash kabuk komut dosyalarında LOT görürsünüz. Ayrıca, bir değişken anahtar durumunun dışında bildirildiğinde ancak başlatılmadığında ve her durum bunu farklı bir şeye başlattığında da görebilirsiniz. Burada, varsayılan değerin de başlatılması gerekir, böylece değişkene erişen satır kodunun aşağısında bir hata oluşmaz.

3. Kodunuzu okuyan birine bu konuyu kapsadığınızı göstermek için.

variable = (variable == "value") ? 1 : 2;
switch(variable)
{
    case 1:
        // something
    case 2:
        // something else
    default:
        // will NOT execute because of the line preceding the switch.
}

Bu çok basitleştirilmiş bir örnektir, ancak asıl nokta, kodu okuyan birinin neden merak etmemesi gerektiğidir variable 1 veya 2'den başka bir şey etmemesi gerektiğidir.


Ben DEĞİL kullanımına düşünebildiğim tek vaka defaultolduğu anahtar onun yerine bariz her alternatif mutlulukla göz ardı edilebilir bir şey kontrol edildiğinde

switch(keystroke)
{
    case 'w':
        // move up
    case 'a':
        // move left
    case 's':
        // move down
    case 'd':
        // move right
    // no default really required here
}

26
Tuş vuruşlarına ilişkin örneğiniz, söylediklerinizin geri kalanıyla çelişmektedir. : | Biraz daha fazla açıklama şöyle mantıklı olacaktır: Bu durumda bir varsayılan umurumda değil çünkü başka bir tuşa basıldığında umursamazsınız, ancak bir değişken geçirilirse beklenenden farklıysa, .
Andrew

1
Aynı zamanda bir GET parametresini kontrol ediyorsanız, kullanıcı get url'yi geçerli olmayan bir şeye her değiştirdiğinde bir istisna yapılmasını istemeyebilirsiniz: [
Andrew

4
@Andrew WASD, bilgisayar oyunu karakter hareketleri için yaygındır. Diğer etkileşimlere diğer tuşlar atanabileceğinden herhangi bir varsayılan eyleme ihtiyacınız olmaz. Bu tür bir anahtarda, hareket fonksiyonları olarak adlandırmak iyidir.
jemiloii

13
Bazı derleyiciler, bir vaka kaçırılırsa bir enum açıldığında uyarır ve varsayılan bir vaka eklemek bu uyarıyı bastırır. Benim durumumda çok yaygın bir hata kaynağı olduğu göz önüne alındığında (bir numaralandırma değeri eklendikten sonra bir yerde bir anahtarı güncellemeyi unutmak), bu varsayılan bir durumu atlamak için çok iyi bir neden gibi görünüyor .
rdb

3
@virusrocks Durumunuz bir numara ise, yine de beklenmedik değerleriniz olabilir. Örneğin, numaralandırmaya yeni bir değer ekler ve bir anahtarı güncellemeyi unutursanız. Ayrıca, bazı dillerde numaralara tamsayı değerleri atayabilirsiniz. C ++ ' enum MyEnum { FOO = 0, BAR = 1 }; MyEnum value = (MyEnum)2;da MyEnum, FOOveya değerine eşit olmayan geçerli bir örnek oluşturur BAR. Bu sorunlardan herhangi biri projenizde hataya neden olursa, varsayılan bir durum hatayı çok hızlı bir şekilde bulmanıza yardımcı olur, genellikle hata ayıklayıcı gerekmez!
cdgraham

54

Hayır.

Varsayılan bir eylem yoksa içerik önemlidir. Ya sadece birkaç değer üzerinde hareket etmeyi önemsiyorsanız?

Bir oyun için tuşlara basma örneğini ele alalım

switch(a)
{
   case 'w':
     // Move Up
     break;
   case 's':
     // Move Down
     break;
   case 'a':
     // Move Left
     break;
   case 'd':
     // Move Right
     break;
}

Ekleme:

default: // Do nothing

Sadece zaman kaybıdır ve hiçbir nedenle kodun karmaşıklığını artırır.


14
İyi örnek. Ancak, basit bir // do nothingyorum ile varsayılan bir madde eklemek, tüm durumları kapsamazsa, bunun 'uygun olmayacağı' diğer anahtar ifadelerinin aksine 'tamam' olduğunu açıkça ortaya koymaktadır.
The Nail

8
Hayır. Kodlama sadece bazı durumları ele almakla ilgili değildir. Ayrıca bir belge görevi görür. Default: yazarak ve // ​​Hiçbir şey yapma veya başka bir şey yapma gibi yorum yaparak, kodun okunabilirliği daha iyi olur.
JongAm Park

22
Diğer yorumlara katılmıyorum. Varsayılanın eklenmesi // Hiçbir şey yapma, kodun nasıl çalıştığını bilmiyorsanız çok az ekler. Bir switch deyimi varsayılan olmadan bakabilir ve varsayılan hiçbir şey yapmak olduğunu biliyorum. Dağınıklık eklemek bunu daha açık hale getirmez.
Robert Noack

Kesinlikle. Aynı post post paramları teslim etme kavramındadır. Önem verdiğiniz kişileri başkalarıyla değil halledersiniz.
Jimmy Kane

2
@jybrd Önceki geliştiricinin varsayılan olarak kasıtlı olarak dışarıda kaldığına güvenmiyorsanız, neden yerleştirildiklerinin doğru olduğuna inanıyorsunuz? Varsayılan değer, tamamen eksik kadar kazara boş olabilir. Bu kadar önemsiz bir şey için bir yorum gerekli değildir. Bu kod karmaşasıdır. Bunun yerine niyetlerinizi göstermek için tam kapsama birimi testleri yazın. (Sadece benim fikrim)
Robert Noack

45

Varsayılan durumda OLMAMASI bazı durumlarda gerçekten yararlı olabilir.

Anahtar durumlarınız numaralandırma değerleriyse, varsayılan bir durum yoksa, herhangi bir vakayı kaçırmazsanız derleyici uyarısı alabilirsiniz. Bu şekilde, gelecekte yeni numaralandırma değerleri eklenirse ve anahtarda bu değerler için vakalar eklemeyi unutursanız, derleme sırasında sorun hakkında bilgi edinebilirsiniz. Numara türüne geçersiz bir değer verildiğinde, kodun işlenmemiş değerler için uygun eylemi gerçekleştirdiğinden emin olmalısınız. Bu nedenle, enum, mola yerine numaralandırma durumuna geri dönebileceğiniz basit durumlar için işe yarayabilir.

enum SomeEnum
{
    ENUM_1,
    ENUM_2,
    // More ENUM values may be added in future
};

int foo(SomeEnum value)
{
    switch (value)
    {
    case ENUM_1:
        return 1;
    case ENUM_2:
        return 2;
    }
    // handle invalid values here
    return 0;
 }

Bu önemli bir gözlem! Java'da daha da geçerlidir, çünkü numaralandırmalara ints yayınlamanıza izin vermez.
Lii

2
Örneğinizde, switch-ifadesinden sonra dönmek yerine bir istisna atabilirsiniz. Bu şekilde, hem derleyici tarafından statik denetime sahip olabilirsiniz hem de beklenmedik bir şey olursa net bir hata alabilirsiniz.
Lii

1
Katılıyorum. Swift başına örnekte, anahtar kapsamlı olmalıdır, aksi takdirde derleyici hatası alırsınız! Varsayılan değer sağlanması, bu yararlı hatayı susturur. Öte yandan, tüm vakalar işlenirse bir varsayılan sağlamak aslında bir derleyici uyarısı atar (ulaşılamaz deyimi).
Andy

1
Sadece bir hata düzeltildi, bu varsayılan olmasaydı Derleyici'den bir uyarıya neden olurdu: bu yüzden genellikle Numaralandırma Üzerinden Geçişin varsayılanları olmamalıdır.
notan

42

Hangi dilde çalışıyor olursanız olun, her zaman varsayılan bir cümle kullanırdım.

İşler yanlış gidebilir. Değerler beklediğiniz gibi olmayacak vb.

Varsayılan bir cümle eklemek istememeniz, olası değerler kümesini bildiğinizden emin olduğunuz anlamına gelir. Olası değerler kümesini bildiğinize inanıyorsanız, değer bu olası değerler kümesinin dışındaysa, bundan haberdar olmak istersiniz - bu kesinlikle bir hatadır.

Java'da her zaman varsayılan bir cümle kullanmanız ve bir hata atmanızın nedeni budur:

switch (myVar) {
   case 1: ......; break;
   case 2: ......; break;
   default: throw new RuntimeException("unreachable");
}

"Ulaşılamayan" dizeden daha fazla bilgi eklemek için hiçbir neden yoktur; gerçekte olursa, değişkenlerin kaynağına ve değerlerine zaten bakmanız gerekecek ve istisna stacktrace bu satır numarasını içerecektir, bu nedenle istisna mesajına daha fazla metin yazarak zaman kaybetmenize gerek yoktur.


39
Bu, throw new RuntimeException("myVar invalid " + myVar);bir hata ayıklayıcı kullanmak ve değişkenleri incelemek zorunda kalmadan hatayı düzeltmek ve düzeltmek için yeterli bilgi verebileceğinden, bu, nadiren ortaya çıkan zor bir sorunsa çoğaltmak zor olabilir.
Chris Dodd

1
Değerin vakalardan biriyle eşleşmemesi bir hata koşulu değilse ne olur?
Gabe

4
Bir hata koşulu değilse, a'ya gerek yoktur default:. Ancak çoğu zaman böyle olmaz, bir kişi varsayılandan çıkar, çünkü kişi myVarasla listelenenlerden başka bir değere sahip olamayacağını düşünür ; ancak değişkenin "muhtemelen" sahip olabileceği değerlerden başka bir değere sahip olması durumunda gerçek hayatta kaç kez şaşırdım. Bu durumlarda, daha sonra başka bir hataya (hata ayıklaması daha zor) veya yanlış cevaba (testlerde göz ardı edilebilir) neden olmak yerine, bunu hemen görmemi sağlayan istisna için minnettarım.
Adrian Smith

2
Adrian ile aynı fikirdeyim. Sert ve erken başarısız.
Slappy

Bu durum, ele alınan değerlerden biri olduğunu belirten bir iddiaya çok benzediğinden, AssertionErrorbunun yerine atmayı tercih ederim . Ayrıca birisinin hatayı yakalama ve yutma şansı daha azdır. RuntimeExceptionmyVar
Philipp Wendler

15

Şirketimde, Aviyonik ve Savunma pazarı için yazılım yazıyoruz ve her zaman varsayılan bir ifade ekliyoruz, çünkü bir anahtar ifadesindeki TÜM vakalar açıkça ele alınmalıdır ('Hiçbir şey yapma' diyen bir yorum olsa bile). Yazılımı yalnızca beklenmedik (hatta imkansız olduğunu düşündüğümüz) değerlerin yanlış davranması veya çökmesi için karşılayamayız.

Varsayılan bir vakanın her zaman gerekli olmadığı tartışılabilir, ancak her zaman gerekmesi halinde, kod analizcilerimiz tarafından kolayca kontrol edilir.


1
Çalıştığım yerde aynı gereksinime sahibim; katı güvenlik kontrollerini geçmek zorunda olan ve genellikle EMI'ye tabi olan gömülü µControllers için kod yazıyoruz. Numaralandırılmış bir değişkenin numaralandırma listesinde olmayan bir değere asla sahip olmayacağını varsaymak sorumsuz olacaktır.
oosterwal

12

Bir "switch" deyimi her zaman varsayılan bir cümle içermeli mi? Hayır . Genellikle bir varsayılan içermelidir .

Varsayılan bir cümle eklemek, yalnızca bir hata koşulu ileri sürmek veya varsayılan bir davranış sağlamak gibi bir şey varsa mantıklıdır. Bir "adil çünkü" dahil kargo kült programlama ve hiçbir değer sağlamaz. Tüm "if" ifadelerinin "else" içermesi gerektiğini söylemenin "geçiş" karşılığıdır.

Aşağıda, hiçbir anlam ifade etmediği önemsiz bir örnek verilmiştir:

void PrintSign(int i)
{
    switch (Math.Sign(i))
    {
    case 1:
        Console.Write("positive ");
        break;
    case -1:
        Console.Write("negative ");
        break;
    default: // useless
    }
    Console.Write("integer");
}

Bu şuna eşdeğerdir:

void PrintSign(int i)
{
    int sgn = Math.Sign(i);
    if (sgn == 1)
        Console.Write("positive ");
    else if (sgn == -1)
        Console.Write("negative ");
    else // also useless
    {
    }
    Console.Write("integer");
}

Katılmıyorum. IMHO, bir varsayılanın var olmaması gereken tek zaman, şimdiye kadar ve hiç bir zaman, girdi kümesinin değişebileceğinin ve mümkün olan her değerin kapsanmasının bir yolu yoksa. Düşünebildiğim en basit durum, tek cevapların (SQL değişene kadar!) Doğru, yanlış ve NULL olduğu bir veritabanından boole değeridir. Başka bir durumda, "Olmamalı!" mantıklı. Kodunuz değişirse ve bir veya daha fazla yeni değeriniz varsa, bunları kodladığınızdan emin olabilirsiniz ve eğer yapmazsanız testleriniz patlar.
Harper Shelby

4
@Harper: Örneğiniz "bir hata koşulu ileri sür" kategorisine girer.
Gabe

Örneğimin norm olduğunu ve mümkün olan her durumun kapandığından ve varsayılanın gerekli olmadığı% 100 emin olabileceği az sayıda durumun istisna olduğunu iddia ediyorum. Cevabınız kulağa hiç gelmeyecek şekilde (en azından bana) gelebilecek şekilde ifade edilmiştir.
Harper Shelby

@Harper: Tamam, hiçbir şey yapma durumunun daha az yaygın olduğunu göstermek için ifadeyi değiştirdim.
Gabe

4
Bence default:bu durumlarda varsayımlarınızı kodlar. Örneğin, ne zaman (ne olumlu ne de olumsuz) sgn==0yazdırmak uygun integermu yoksa bu bir hata mı? Bana göre bu kodu okumak zor. zeroBu durumda yazmak istemeyeceğinizi integerve programcının sgnyalnızca -1 veya +1 olabileceği varsayımını yaptığını varsayıyorum . Bu durumda, default:programcının varsayım hatasını erken yakalamasına ve kodu değiştirmesine izin vermesi.
Adrian Smith

7

Gördüğüm kadarıyla cevap 'varsayılan' isteğe bağlıdır, bir anahtarın her zaman bir varsayılan içermesi gerektiğini söylemek her 'if-elseif' bir 'else' içermesi gerektiğini söylemek gibidir. Varsayılan olarak yapılacak bir mantık varsa, 'default' ifadesi orada olmalıdır, ancak aksi takdirde kod hiçbir şey yapmadan yürütülmeye devam edebilir.


6

Gerçekten gerekmediğinde varsayılan bir cümleye sahip olmak Defansif programlama Bu, çok fazla hata işleme kodu nedeniyle genellikle aşırı karmaşık olan koda yol açar. Bu hata işleme ve algılama kodu, kodun okunabilirliğine zarar verir, bakımı zorlaştırır ve sonunda çözdüğünden daha fazla hataya yol açar.

Bu yüzden varsayılana ulaşılmaması gerekiyorsa - eklemeniz gerekmediğine inanıyorum.

"Ulaşılmaması gereken" ifadesinin, yazılımda bir hata olması durumunda kullanıcı girişi vb. Nedeniyle istenmeyen değerler içerebilecek değerleri test etmeniz gerektiğini belirtir.


3
Beklenmedik durumlar için başka bir yaygın neden: Kodun diğer bölümleri, belki yıllar sonra değiştirilir.
Hendrik Brummermann

Gerçekten de bu çok tehlikeli bir davranış. En azından bir assert () cümlesi eklerdim. Daha sonra bir hata olduğunda kolayca algılanır.
Kurt Pattyn

5

Dile bağlı olduğunu söyleyebilirim, ancak bir enum türünü açıyorsanız ve olası her değeri işlerseniz, muhtemelen varsayılan bir durum dahil DEĞİLDİR. Bu şekilde, daha sonra ek bir numaralandırma etiketi ekler ve anahtara eklemeyi unutursanız, yetkili bir derleyici size eksik vaka hakkında bir uyarı verecektir.


5
"Mümkün olan her değerin" numaralandırmalarla ele alınması olası değildir. Belirli bir değer açıkça tanımlanmamış olsa bile bir enum'a bir tam sayı atayabilirsiniz. Ve hangi derleyici kayıp dava hakkında uyarıyor?
TrueWill

1
@TrueWill: Evet, anlaşılması imkansız olan gizli kodu yazmak için açık dökümler kullanabilirsiniz; anlaşılır bir kod yazmak için bundan kaçınmalısınız. gcc -Wall(yetkili derleyicilerin en düşük ortak paydası) anahtar ifadelerinde işlenmeyen numaralandırmalar hakkında uyarılar verir.
Chris Dodd

4

Switch deyiminin yalnızca kesin olarak tanımlanmış bir etiket veya değer kümesi olacağını biliyorsanız, bunu yalnızca temelleri kapsayacak şekilde yapın, böylece her zaman geçerli sonuç elde edersiniz. diğer değerler için en iyi işleyici olun.

switch(ResponseValue)
{
    default:
    case No:
        return false;
    case Yes;
        return true;
}

defaultBurada kolon hala gerekli mi? Yoksa bunu atlamanıza izin veren bazı özel sözdizimine izin veriyor mu?
Ponkadoodle

Kolon gereklidir, bu bir yazım hatasıydı, dikkatime sunduğunuz için teşekkür ederim.
deegee

3

En azından Java için zorunlu değildir. JLS'ye göre, en az bir varsayılan vakanın mevcut olabileceğini söylüyor. Bu, varsayılan bir durumun kabul edilemeyeceği anlamına gelir. Bu bazen anahtar deyimini kullandığınız bağlama da bağlıdır. Örneğin Java'da, aşağıdaki anahtar bloğu varsayılan durum gerektirmez

private static void switch1(String name) {
    switch (name) {
    case "Monday":
        System.out.println("Monday");
        break;
    case "Tuesday":
        System.out.println("Tuesday");
        break;
    }
}

Ancak bir String döndürmeyi bekleyen aşağıdaki yöntemde, varsayılan durum derleme hatalarından kaçınmak için kullanışlı olur

    private static String switch2(String name) {
    switch (name) {
    case "Monday":
        System.out.println("Monday");
        return name;

    case "Tuesday":
        System.out.println("Tuesday");
        return name;

    default:
        return name;
    }
}

ancak, yalnızca sonunda bir döndürme ifadesi kullanarak varsayılan duruma sahip olmadan yukarıdaki yöntem için derleme hatasını önleyebilirsiniz, ancak varsayılan durum sağlamak bunu daha okunabilir hale getirir.


3

MISRA C gibi bazı (eski) kılavuzlar böyle söylüyor :

Son bir varsayılan cümle için gereklilik savunma amaçlı programlamadır. Bu madde ya uygun önlem almalı ya da neden hiçbir işlem yapılmadığına dair uygun bir yorum içermelidir.

Bu öneri güncel değildir, çünkü şu anda ilgili ölçütlere dayanmamaktadır. Göze çarpan ihmal Harlan Kassler'in söylediği şey:

Varsayılan büyük durumu bırakmak, derleyicinin işlenmemiş bir durum gördüğünde isteğe bağlı olarak uyarmasını veya başarısız olmasını sağlar. Her şeyden önce statik doğrulanabilirlik herhangi bir dinamik kontrolden daha iyidir ve bu nedenle dinamik kontrole ihtiyacınız olduğunda değerli bir fedakarlık yapmaz.

Harlan'ın da gösterdiği gibi, varsayılan bir vakanın işlevsel eşdeğeri anahtardan sonra yeniden oluşturulabilir. Bu, her vaka erken bir dönüş olduğunda önemsizdir.

Dinamik bir kontrol için tipik ihtiyaç, geniş anlamda giriş işlemedir. Programın kontrolünün dışından bir değer gelirse buna güvenilemez.

Bu aynı zamanda Misra'nın aşırı savunma programcılığı bakış açısını aldığı yerdir , böylece geçersiz bir değer fiziksel olarak temsil edilebilir olduğu sürece, programın doğru olup olmadığı fark edilmeden kontrol edilmelidir. Bu, yazılımın donanım hatalarının varlığında mümkün olduğunca güvenilir olması gerektiğinde mantıklıdır. Ancak Ophir Yoktan'ın dediği gibi, çoğu yazılım hataları "ele almamak" için daha iyidir. İkinci uygulamaya bazen saldırgan programlama denir .


2

Gelmesi beklenen değerleri yakalamak için bir varsayılan olması gerekir.

Ancak, Adrian Smith ile varsayılan hata mesajınızın tamamen anlamsız bir şey olması gerektiğini kabul etmiyorum. Kullanıcınızı göreceğiniz ("ulaşılamayan" gibi bir mesaj tamamen anlamsızdır ve bu durumda kimseye yardım etmez.

Durumda, kaç kez tamamen anlamsız bir BSOD yaşadınız? Yoksa ölümcül bir istisna @ 0x352FBB3C32342?


Örneğin, hata mesajlarını her zaman gören yalnızca geliştirici olmadığını unutmayın. Gerçek dünyada yaşıyoruz, insanlar hata yapıyor.
John Hunt

2

Anahtar değeri ( anahtar (değişken )) varsayılan duruma ulaşamazsa, varsayılan duruma hiç gerek yoktur. Varsayılan durumu koretsek bile, hiç yürütülmez. Ölü kod.


2

Opsiyonel bir kodlama 'sözleşmesidir'. Kullanıma bağlı olarak gerekli olup olmadığıdır. Şahsen ben buna ihtiyacınız yoksa orada olmaması gerektiğine inanıyorum. Neden kullanıcı tarafından kullanılmayacak veya ulaşmayacak bir şey eklemelisiniz?

Vaka olasılıkları sınırlıysa (yani bir Boolean), varsayılan fıkra gereksizdir !


2

Bir switchdeyimde varsayılan bir durum yoksa, bu durum bir aşamada ortaya çıkarsa, bu durum geliştirme aşamasında öngörülemeyen bir davranış olabilir. Bir defaultdava eklemek iyi bir uygulamadır .

switch ( x ){
  case 0 : { - - - -}
  case 1 : { - - - -}
}

/* What happens if case 2 arises and there is a pointer
* initialization to be made in the cases . In such a case ,
* we can end up with a NULL dereference */

Böyle bir uygulama, NULL dereference , bellek sızıntısı ve diğer ciddi hata türlerine neden olabilir. .

Örneğin, her koşulun bir işaretçi başlattığını varsayarız. Ancak, defaultvakanın ortaya çıkması gerekiyorsa ve bu durumda başlatmazsak, boş bir işaretçi istisnasıyla her iniş olasılığı vardır. Bu nedenle default, önemsiz olsa da, bir vaka bildirimi kullanılması önerilir .


2

Enum tarafından kullanılan anahtarda varsayılan durum gerekli olmayabilir. anahtar tüm değeri içerdiğinde, varsayılan durum hiçbir zaman yürütülmez. Bu durumda, gerekli değildir.


1

Belirli bir dilde anahtarın nasıl çalıştığına bağlıdır, ancak hiçbir dilde hiçbir eşleşme olmadığında, yürütme uyarı vermeden switch deyiminden geçer. Bazı değerler kümesi beklediğinizi ve bunları anahtarda işlediğinizi, ancak girdide başka bir değer elde ettiğinizi düşünün. Hiçbir şey olmuyor ve hiçbir şey olmadığını bilmiyorsunuz. Davayı varsayılan olarak yakaladıysanız, yanlış bir şey olduğunu bilirsiniz.


1

Yukarıdaki Vanwaril'in en çok oylanan yanıtıyla aynı fikirde değilim.

Herhangi bir kod karmaşıklık ekler. Ayrıca bunun için testler ve dokümantasyon yapılmalıdır. Bu yüzden daha az kod kullanarak programlamak her zaman iyidir. Benim düşüncem, kapsamlı anahtar ifadeleri için varsayılan bir yan tümce kullanırken ben kapsamlı olmayan anahtar ifadeleri için varsayılan bir yan tümcesi kullanmak olduğunu. Bunu doğru yaptığımdan emin olmak için bir statik kod analiz aracı kullanıyorum. Şimdi ayrıntılara girelim:

  1. Kapsamlı olmayan anahtar ifadeleri: Bunların her zaman varsayılan bir değeri olmalıdır. Adından da anlaşılacağı gibi, bunlar olası tüm değerleri içermeyen ifadelerdir. Bu da mümkün olmayabilir, örneğin bir tamsayı değerinde veya bir String üzerinde bir switch deyimi. Burada Vanwaril örneğini kullanmak istiyorum (Yanlış bir öneri yapmak için bu örneği kullandığını düşünüyorum. Ben burada tersini belirtmek için kullanın -> Varsayılan bir ifade kullanın):

    switch(keystroke)
    {
      case 'w':
        // move up
      case 'a':
        // move left
      case 's':
        // move down
      case 'd':
        // move right
      default:          
        // cover all other values of the non-exhaustive switch statement
    }
    

    Oynatıcı başka herhangi bir tuşa basabilir. Sonra hiçbir şey yapamadık (bu, yalnızca varsayılan duruma bir yorum ekleyerek kodda gösterilebilir) veya örneğin ekranda bir şey yazdırmalıdır. Bu durum, olabileceği için konuyla ilgilidir.

  2. Kapsamlı anahtar ifadeleri: Bu anahtar ifadeleri olası tüm değerleri kapsar, örneğin, sınıf sistemi türlerinin numaralandırılmasıyla ilgili bir anahtar ifadesi. İlk kez kod geliştirirken tüm değerleri kapsamak kolaydır. Bununla birlikte, biz insan olarak bazılarını unutmak için küçük bir şans var. Ayrıca daha sonra bir enum değeri eklerseniz, tüm switch deyimlerinin tam olmasını sağlayacak şekilde uyarlanması gerekir, hata cehenneminin yolunu açar. Basit çözüm, statik bir kod analiz aracıdır. Araç, tüm anahtar ifadelerini kontrol etmeli ve bunların kapsamlı olup olmadığını veya varsayılan bir değere sahip olup olmadığını kontrol etmelidir. Burada kapsamlı bir anahtar ifadesi için bir örnek. İlk önce bir numaraya ihtiyacımız var:

    public enum GradeSystemType {System1To6, SystemAToD, System0To100}
    

    O zaman bu sıralamanın bir değişkenine ihtiyacımız var GradeSystemType type = .... Daha sonra kapsamlı bir anahtar ifadesi şöyle görünecektir:

    switch(type)
    {
      case GradeSystemType.System1To6:
        // do something
      case GradeSystemType.SystemAToD:
        // do something
      case GradeSystemType.System0To100:
        // do something
    }
    

    Bu nedenle GradeSystemType, örneğin System1To3, statik kod analiz aracını genişletirsek, varsayılan bir hüküm olmadığını ve switch deyiminin kapsamlı olmadığını tespit etmeliyiz, bu yüzden tasarruf ediyoruz.

Ek bir şey daha var. Her zaman bir defaultcümle kullanırsak , statik kod analiz aracının her zaman cümleyi tespit ettiği için ayrıntılı veya kapsamlı olmayan anahtar ifadelerini tespit defaultedemeyebilir. Numarayı başka bir değerle genişletirsek ve bir anahtar ifadesine eklemeyi unutursak, bu çok kötü bir durumdur.


0

Anahtar ifadeleri her zaman varsayılan bir cümle içermeli mi? Varsayılan durum dışında anahtar durumu bulunamaz, anahtar durumunda varsayılan durum switch(x)bu durumda x diğer durum değerleriyle eşleşmediğinde anahtar değerini tetikler .


0

Bu oldukça dile özgü ve C ++ durumda enum sınıfı için küçük bir nokta olduğuna inanıyorum türü . Hangi geleneksel C enum daha güvenli görünüyor. FAKAT

Eğer std :: byte uygulanmasına bakarsanız onun gibi bir şey:

enum class byte : unsigned char {} ;

Kaynak: https://en.cppreference.com/w/cpp/language/enum

Ayrıca şunu da düşünün:

Aksi takdirde, T, altta yatan sabit tiple kapsamlandırılmış veya kapsamı kapatılmamış bir numaralandırma türüyse ve hazırlanmış init listesinin yalnızca bir başlatıcısı varsa ve başlatıcıdan altta yatan türe dönüşümün daralmadığı ve başlatma doğrudan liste başlatmadır, daha sonra numaralandırma, başlatıcıyı altta yatan tipe dönüştürmenin sonucu ile başlatılır.

(C ++ 17'den beri)

Kaynak: https://en.cppreference.com/w/cpp/language/list_initialization

Enumerator tanımlı olmayan değerleri temsil eden enum sınıfının bir örneğidir. Bu nedenle numaralara tam güvenemezsiniz. Uygulamaya bağlı olarak bu önemli olabilir.

Ancak, @Harlan Kassler'in görevinde söylediklerini gerçekten çok seviyorum ve bu stratejiyi bazı durumlarda kendim kullanmaya başlayacağım.

Güvensiz numaralandırma sınıfına sadece bir örnek:

enum class Numbers : unsigned
{
    One = 1u,
    Two = 2u
};

int main()
{
    Numbers zero{ 0u };
    return 0;
}
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.