it-swarm-tr.com

Switch ifadesinde birden fazla vaka

Tekrar tekrar case value: belirtmeden birden fazla vaka ifadesine girmenin bir yolu var mı?

Bunun işe yaradığını biliyorum:

switch (value)
{
   case 1:
   case 2:
   case 3:
      //do some stuff
      break;
   case 4:
   case 5:
   case 6:
      //do some different stuff
      break;
   default:
       //default stuff
      break;
}

ama böyle bir şey yapmak isterdim:

switch (value)
{
   case 1,2,3:
      //Do Something
      break;
   case 4,5,6:
      //Do Something
      break;
   default:
      //Do the Default
      break;
}

Bu, farklı bir dilden düşündüğüm sözdizimi mi, yoksa bir şey mi eksik?

517
theo

Bahsettiğiniz ikinci yöntem için C++ veya C # dilinde sözdizimi yoktur.

İlk yönteminde yanlış bir şey yok. Ancak, çok büyük aralıklarınız varsa, sadece if ifadeleri dizisini kullanın.

282
Brian R. Bondy

Sanırım bu çoktan cevaplandı. Bununla birlikte, her iki seçeneği de sözdizimi açısından daha iyi bir şekilde şu şekilde karıştırabileceğinizi düşünüyorum:

switch (value)
{
case 1: case 2: case 3:          
    // Do Something
    break;
case 4: case 5: case 6: 
    // Do Something
    break;
default:
    // Do Something
    break;
}
640

Bu sözdizimi Visual Basic'tir Seç ... Örnek Açıklama :

Dim number As Integer = 8
Select Case number
    Case 1 To 5
        Debug.WriteLine("Between 1 and 5, inclusive")
        ' The following is the only Case clause that evaluates to True.
    Case 6, 7, 8
        Debug.WriteLine("Between 6 and 8, inclusive")
    Case Is < 1
        Debug.WriteLine("Equal to 9 or 10")
    Case Else
        Debug.WriteLine("Not between 1 and 10, inclusive")
End Select

Bu sözdizimini C # dilinde kullanamazsınız. Bunun yerine, ilk örneğinizdeki sözdizimini kullanmanız gerekir.

65
Neal

Orijinal soru için biraz geç, ancak bu cevabı daha yeni bir sürüm kullanan birinin ( C # 7 - varsayılan olarak Visual Studio 2017/.NET Framework 4.6.2 ) kullanabileceğini umuyorum. , yararlı bulacaktır.

C # 7'de, anahtar ifadesi ile aralık tabanlı anahtarlama artık mümkündür ve OP'nin sorununa yardımcı olabilir.

Örnek:

int i = 5;

switch (i)
{
    case int n when (n >= 7):
        Console.WriteLine($"I am 7 or above: {n}");
        break;

    case int n when (n >= 4 && n <= 6 ):
        Console.WriteLine($"I am between 4 and 6: {n}");
        break;

    case int n when (n <= 3):
        Console.WriteLine($"I am 3 or less: {n}");
        break;
}

// Output: I am between 4 and 6: 5

Notlar:

  • ( ve ) parantezleri when koşulunda gerekli değildir, ancak bu örnekte karşılaştırmaları vurgulamak için kullanılır.
  • var ayrıca int yerine kullanılabilir. Örneğin: case var n when n >= 7:.
47
Steve Gomez

Size veren newline'ı dışlayabilirsiniz:

case 1: case 2: case 3:
   break;

ama ben bu kötü tarzı düşünüyorum.

31
Allan Wind

.NET Framework 3.5'in aralıkları var:

Numaralandırılabilir. MSDN’den gelen aralık

sWITCH deyiminin "==" işlecini kullandığını söylediği gibi, onu "include" ve IF ifadesiyle kullanabilirsiniz.

İşte bir örnek:

int c = 2;
if(Enumerable.Range(0,10).Contains(c))
    DoThing();
else if(Enumerable.Range(11,20).Contains(c))
    DoAnotherThing();

Fakat bence daha çok eğlenebiliriz: dönüş değerlerine ihtiyaç duymayacağınız ve bu işlem parametreleri almadığı için eylemleri kolayca kullanabilirsiniz!

public static void MySwitchWithEnumerable(int switchcase, int startNumber, int endNumber, Action action)
{
    if(Enumerable.Range(startNumber, endNumber).Contains(switchcase))
        action();
}

Bu yeni yöntemle eski örnek:

MySwitchWithEnumerable(c, 0, 10, DoThing);
MySwitchWithEnumerable(c, 10, 20, DoAnotherThing);

Değerleri değil eylemleri geçtiğiniz için parantezi atlamalısınız, bu çok önemlidir. Argümanlar ile işleve ihtiyacınız varsa, Action türünü Action<ParameterType> olarak değiştirin. Dönen değerlere ihtiyacınız varsa, Func<ParameterType, ReturnType> kullanın.

C # 3.0'da kolay Kısmi Uygulama / durum parametresi aynı olduğu gerçeğini kapsüllemek mümkün değildir, ancak küçük bir yardımcı yöntem (biraz ayrıntılı, tho) yaratırsınız.

public static void MySwitchWithEnumerable(int startNumber, int endNumber, Action action){ 
    MySwitchWithEnumerable(3, startNumber, endNumber, action); 
}

İşte yeni işlevsel ithal ifadesinin IMHO'nun eski zorunlu ifadeden daha güçlü ve zarif olmasının bir örneği.

18
Luca Molteni

@ Jennifer Owens: kesinlikle haklısınız, aşağıdaki kod işe yaramaz:

case 1 | 3 | 5:
//not working do something

Bunu yapmanın tek yolu:

case 1: case 2: case 3:
// do something
break;

Aradığınız kod, herhangi bir anahtar seçeneğinde kolayca aralıklar koyabileceğiniz görsel temel üzerinde çalışır veya başka bir engel varsa, çok aşırı bir noktada,. c # projenize.

Not: Visual Basic'te eşdeğer anahtarı seçme durumu.

8
none

Başka bir seçenek rutin kullanmak olacaktır. Durum 1-3'ün tümü aynı mantığı uygularsa, o zaman bu mantığı bir rutine sarın ve her vaka için arayın. Bunun aslında durum ifadelerinden kurtulmadığını biliyorum, ancak iyi bir stil uyguluyor ve bakımı minimumda tutuyor….

[Düzenle] Orijinal soruyla eşleştirmek için alternatif uygulama eklendi ... [/ Düzenle]

switch (x)
{
   case 1:
      DoSomething();
      break;
   case 2:
      DoSomething();
      break;
   case 3:
      DoSomething();
      break;
   ...
}

private void DoSomething()
{
   ...
}

Alt

switch (x)
{
   case 1:
   case 2:
   case 3:
      DoSomething();
      break;
   ...
}

private void DoSomething()
{
   ...
}
7
Dr8k

gcc, sıralı aralıkları desteklemek için C diline bir uzantı uygular:

switch (value)
{
   case 1...3:
      //Do Something
      break;
   case 4...6:
      //Do Something
      break;
   default:
      //Do the Default
      break;
}

Düzenle: Sadece sorudaki C # etiketini fark ettim, bu yüzden muhtemelen bir gcc cevabı işe yaramadı.

5
DGentry

İşte komple C # 7 çözümü ...

switch (value)
{
   case var s when new[] { 1,2,3 }.Contains(s):
      //Do Something
      break;
   case var s when new[] { 4,5,6 }.Contains(s):
      //Do Something
      break;
   default:
      //Do the Default
      break;
}

Dizelerle de çalışır ...

switch (mystring)
{
   case var s when new[] { "Alpha","Beta","Gamma" }.Contains(s):
      //Do Something
      break;
...
}
5
Carter Medlin

switch in C # 'tan daha az bilinen bir yönü, operator = ' ye dayanmasıdır ve geçersiz kılınabileceği için buna benzer bir şeye sahip olabilirsiniz:


string s = foo();

switch (s) {
  case "abc": /*...*/ break;
  case "def": /*...*/ break;
}
5

Aslında GOTO komutundan da hoşlanmıyorum, ancak resmi MS materyallerinde var, hepsi izin verilen sözdizimleri.

Bir anahtar bölümünün ifade listesinin bitiş noktasına ulaşılabilirse, bir derleme zamanı hatası oluşur. Bu, "düşmemesi" kuralı olarak bilinir. Örnek

switch (i) {
case 0:
   CaseZero();
   break;
case 1:
   CaseOne();
   break;
default:
   CaseOthers();
   break;
}

hiçbir anahtar bölümünün erişilebilir bir bitiş noktası olmadığından geçerlidir. C ve C++ 'dan farklı olarak, bir anahtar bölümünün yürütülmesinin bir sonraki anahtar bölümüne ve örneğin "geçmesine" izin verilmez

switch (i) {
case 0:
   CaseZero();
case 1:
   CaseZeroOrOne();
default:
   CaseAny();
}

derleme zamanı hatasıyla sonuçlanır. Bir anahtar bölümünün yürütülmesinin başka bir anahtar bölümünün yürütülmesi ile takip edilmesi gerektiğinde, açık bir goto durum veya varsayılan bir goto ifadesi kullanılmalıdır:

switch (i) {
case 0:
   CaseZero();
   goto case 1;
case 1:
   CaseZeroOrOne();
   goto default;
default:
   CaseAny();
   break;
}

Bir anahtarlama bölümünde birden fazla etikete izin verilir. Örnek

switch (i) {
case 0:
   CaseZero();
   break;
case 1:
   CaseOne();
   break;
case 2:
default:
   CaseTwo();
   break;
}

Bu özel durumda, GOTO'nun kullanılabileceğine inanıyorum, aslında ilk adım atmanın tek yolu bu.

kaynak: http://msdn.Microsoft.com/en-us/library/aa664749%28v=vs.71%29.aspx

3
Jiří Herník

Daha iyi görünmek veya daha iyi çalışmak için C # en az kullanılan sözdizimlerinden birini elde etmenin yollarını bulmak için çok fazla çalışma yapıldığı görülüyor. Şahsen ben switch deyimini nadiren kullanmaya değer buluyorum. Hangi verileri test ettiğinizin ve istediğiniz son sonuçları analiz etmenizi şiddetle tavsiye ederim.

Örneğin, asal sayılar olup olmadıklarını görmek için bilinen bir aralıktaki değerleri hızlı bir şekilde test etmek istediğinizi varsayalım. Kodunuzu israf eden hesaplamaları yapmaktan kaçınmak istersiniz ve çevrimiçi olarak istediğiniz aralıkta bir asalların listesini bulabilirsiniz. Her bir değeri bilinen asal sayılarla karşılaştırmak için büyük bir anahtar ifadesi kullanabilirsiniz.

Ya da sadece bir asal dizilim haritası oluşturabilir ve anında sonuç alabilirsiniz:

    bool[] Primes = new bool[] {
        false, false, true, true, false, true, false,    
        true, false, false, false, true, false, true,
        false,false,false,true,false,true,false};
    private void button1_Click(object sender, EventArgs e) {
        int Value = Convert.ToInt32(textBox1.Text);
        if ((Value >= 0) && (Value < Primes.Length)) {
            bool IsPrime = Primes[Value];
            textBox2.Text = IsPrime.ToString();
        }
    }

Belki bir dizgede bir karakterin onaltılık olup olmadığını görmek istersiniz. Eski ve biraz büyük bir switch ifadesi kullanabilirsiniz.

Ya da karakteri sınamak için normal ifadeleri kullanabilir ya da bilinen onaltılı harflerden oluşan bir dizgede karakteri aramak için IndexOf işlevini kullanabilirsiniz:

        private void textBox2_TextChanged(object sender, EventArgs e) {
        try {
            textBox1.Text = ("0123456789ABCDEFGabcdefg".IndexOf(textBox2.Text[0]) >= 0).ToString();
        } catch {
        }
    }

1 ile 24 arasında değişen bir değere bağlı olarak 3 farklı eylemden birini yapmak istediğinizi varsayalım. Bir dizi IF ifadesi kullanmanızı öneririm. Ve eğer bu çok karmaşık hale geldiyse (Ya da sayılar, 1 ila 90 aralığındaki bir değere bağlı olarak 5 farklı eylem gibi daha büyüktü), o zaman eylemleri tanımlamak ve enumların bir dizi haritasını oluşturmak için bir enum kullanın. Değer daha sonra dizi haritasına endekslemek ve istediğiniz eylemin numaralandırmasını almak için kullanılır. Ardından, sonuçtaki enum değerini işlemek için küçük bir IF ifadesi kümesi veya çok basit bir anahtar ifadesi kullanın.

Ayrıca, bir dizi değeri eylemlere dönüştüren dizi haritasındaki Güzel şey, kodla kolayca değiştirilebilmesidir. Sabit kablolu kodla çalışma zamanında kolayca davranış değiştiremezsiniz, ancak bir dizi harita ile kolaydır.

2
Darin

Çok büyük miktarda dizginiz varsa (veya başka bir türde) Hepsi aynı şeyi yapıyorsa, string.Contains özelliğiyle birlikte bir dize listesinin kullanılmasını öneririm.

Öyleyse şöyle büyük bir anahtar ifadeniz varsa:

switch (stringValue)
{
    case "cat":
    case "dog":
    case "string3":
    ...
    case "+1000 more string": //Too many string to write a case for all!
        //Do something;
    case "a lonely case"
        //Do something else;
    .
    .
    .
}

Bunu şöyle bir if ifadesiyle değiştirmek isteyebilirsiniz:

//Define all the similar "case" string in a List
List<string> listString = new List<string>(){ "cat", "dog", "string3", "+1000 more string"};
//Use string.Contains to find what you are looking for
if (listString.Contains(stringValue))
{
    //Do something;
}
else
{
    //Then go back to a switch statement inside the else for the remaining cases if you really need to
}

Bu ölçek, herhangi bir sayı dizge durumu için iyi.

1
Maxter

Sadece sohbete eklemek için .NET 4.6.2 kullanarak aşağıdakileri de yapabildim. Kodu test ettim ve benim için işe yaradı.

Aşağıdaki gibi birden fazla "VEYA" ifadesi de yapabilirsiniz:

            switch (value)
            {
                case string a when a.Contains("text1"):
                    // Do Something
                    break;
                case string b when b.Contains("text3") || b.Contains("text4") || b.Contains("text5"):
                    // Do Something else
                    break;
                default:
                    // Or do this by default
                    break;
            }

Dizideki bir değerle eşleşip eşleşmediğini de kontrol edebilirsiniz:

            string[] statuses = { "text3", "text4", "text5"};

            switch (value)
            {
                case string a when a.Contains("text1"):
                    // Do Something
                    break;
                case string b when statuses.Contains(value):                        
                    // Do Something else
                    break;
                default:
                    // Or do this by default
                    break;
            }
0
JeffS