Anahtar deyiminde birden çok vaka


582

case value:Tekrar tekrar belirtmeden birden fazla vaka deyiminden geçmenin 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 istiyorum:

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

Bu sözdizimi farklı bir dilden mi, yoksa bir şey mi kaçırıyorum?


Sadece bir IF deyimi kullanmamanın bir nedeni var mı (bir dizi ints kontrol ediyorsanız)?
Eric Schoonover

2
evet charlse, ilk yol iyi çalışıyor, birçok yerde kullandım. İstediğimden daha kirli, ama faydalı. Bu tam sayıları örnek olarak kullandım. Gerçek veriler daha çeşitlidir. Bir if (1 || 2 || 3) {...} başka (4 || 5 || 6) {...} da çalışsaydı, ama okumak daha zor.
Theo

5
neden bir öncekinden daha sonuncuyu düşünüyorsun. İkincisi ,, başka bir c tarzı dil ile paylaşılmayan ve başka bir anlam katar . Bu benim için çok daha kirli görünüyor.
Jon Hanna

1
Ruby'nin 2. sözdizimini almış olabilirsiniz. Bu dilde bu şekilde çalışır (her ne kadar anahtar durum olursa ve durum ne zaman, diğer şeylerin yanı sıra olur.)
juanpaco

4
Önemli Not . C # v7'den itibaren anahtar kasasında aralıklar desteklenir - Lütfen Steve
RBT

Yanıtlar:


313

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

İlk yönteminizde yanlış bir şey yok. Ancak çok büyük aralıklarınız varsa, bir dizi if ifadesi kullanın.



Kullanıcı bir dizi numaralandırmaya girişi azaltmak ve numaralandırmayı açmak için bazı if's (veya tablo araması) kullanabilir.
Harvey

5
muhtemelen
VB.net'ten

1
VB.net çeşitli durum ifadeleri için daha iyidir ... C # yaptığı gibi bırakmayın dışında. Biraz al, biraz ver.
Brain2000

Bunun artık doğru olmadığına inanıyorum. Bkz. Stackoverflow.com/questions/20147879/… . Ayrıca bu soru üzerine bir cevap var stackoverflow.com/a/44848705/1073157
Dan Rayson

700

Sanırım bu zaten cevaplandı. Ancak, yine de her iki seçeneği de sözdizimsel olarak daha iyi bir ş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;
}

3
'switch' c # için küçük harf olmalı?
Austin Harris

3
Daraltılmış kod, sorunun ilk örneğine genişletilir. Sadece soruda olduğu gibi yapabilir.
MetalPhoenix

10
Neden rahatsız oluyorsun? Visual Studio 2013'teki otomatik girinti, bunu yine de orijinal sorudaki formata döndürecektir.
Gustav

14
@T_D destek alıyor çünkü aslında soruya cevap veriyor. OP dedi ki, bir şey mi özlüyorum ... Carlos cevapsız olanla cevap verdi. Bana çok kesilmiş ve kurutulmuş görünüyor. 422 upvotes aldığından nefret etmeyin.
Mike Devenney

8
@MikeDevenney Sonra doğru cevap "hayır, c # bunun için herhangi bir sözdizimi yok" olacağını gördüğüm kadar, soru farklı yorumladı. Birisi "Baş aşağı tuttuğum bir bardağa sıvı dökmek mümkün mü?" cevap "hayır" olmalı ve "baş aşağı bakıp hayal gücünüzü kullanırsanız sıvı dökebilirsiniz" olmalıdır, çünkü bu cevap tamamen hayal gücünü kullanmakla ilgilidir. Normal sözdizimini kullanır ancak kötü biçimlendirirseniz, biraz hayal gücüyle diğer sözdizimine benzer. Umarım benim açımdan ...: P
T_D

74

Bu sözdizimi Visual Basic Select ... Vaka Bildirimi'nden alınmıştır :

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 # içinde kullanamazsınız. Bunun yerine, ilk örneğinizdeki sözdizimini kullanmanız gerekir.


49
* kaçırdığım birkaç şeyden biri bu.
nickf

10
Burada, visual basic'in çirkin olmadığı ve c # 'dan daha çok yönlü olduğu birkaç ekrandan birine sahibiz. Bu değerli bir örnek!
bgmCoder

Bu oldukça iyi. Bunun neden C # 8.0 ile eklenmediğini merak ediyorum. Çok iyi olurdu.
Sigex

69

C # 7'de (varsayılan olarak Visual Studio 2017 / .NET Framework 4.6.2'de kullanılabilir), aralık tabanlı anahtarlama artık switch deyimi ile mümkündür ve OP'nin sorununa yardımcı olacaktır.

Misal:

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:

  • Parantezler (ve koşulda )gerekli değildir when, ancak bu örnekte karşılaştırmaları vurgulamak için kullanılır.
  • varyerine kullanılabilir int. Örneğin: case var n when n >= 7:.

3
Bu (kalıp eşleşmesi) genellikle C # 7.x veya üstünü kullanabileceğiniz en iyi yöntem olmalıdır, çünkü diğer cevaplardan çok daha açıktır.
UndyingJellyfish

Bunu bir Enums listesi ile başarmanın bir yolu var mı? Numaralandırmalar int ile nereye eşlenir?
Sigex

33

Size aşağıdakileri sağlayan yeni satırı dışarıda bırakabilirsiniz:

case 1: case 2: case 3:
   break;

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


20

.NET Framework 3.5'in aralıkları vardır:

Numaralandırılabilir. MSDN'den menzil

SWITCH deyiminin "==" operatörünü kullandığı gibi, "include" ve IF deyimiyle kullanabilirsiniz.

İşte bir örnek:

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

Ama bence daha fazla eğlenebiliriz: dönüş değerlerine ihtiyacınız olmayacağından ve bu eylem parametre almadığından, işlemleri 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 parantezini atlamanız gerekir, bu çok önemlidir. Eğer argümanlarla işlevini gerekiyorsa, sadece türünü değiştirmek Actioniçin Action<ParameterType>. Dönüş değerlerine ihtiyacınız varsa kullanın Func<ParameterType, ReturnType>.

C # 3.0'da case parametresinin aynı olduğu gerçeğini kapsüllemek için kolay Kısmi Uygulama yoktur , ancak küçük bir yardımcı yöntem (biraz ayrıntılı, tho) oluşturursunuz.

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

Burada, yeni işlevsel içe aktarılan ifadenin IMHO'nun eski zorunlu olandan daha güçlü ve zarif olduğuna bir örnek.


3
İyi seçim. Unutulmaması gereken bir şey olsa da - Enumerable.Range'ın argümanları int startve int count. Örnekleriniz yazıldıkları gibi çalışmaz. Bunu ikinci argüman gibi yazıyorsunuz int end. Örneğin - Enumerable.Range(11,20)11 ile başlayan 20 rakamla sonuçlanır ve 11 ile 20 arasındaki rakamlarla sonuçlanmaz.
Gabriel McAdams

bir Enum ile çalışıyorsanız, neden böyle bir şey olmasın? if (Enumerable.Range (MyEnum.A, MyEnum.M) {DoThing ();} else if (Enumerable.Range (MyEnum.N, MyEnum.Z) {DoAnotherThing ();}
David Hollowell - MSFT

4
Not Enumerable.Range(11,20).Contains(c)eşdeğerdir for(int i = 11; i < 21; ++i){ if (i == c) return true; } return false;bunu sadece kullanırken, uzun zaman alacağını geniş bir ürün yelpazesi olsaydı >ve <hızlı ve sürekli zamanlı olacaktır.
Jon Hanna

İyileştirme: MySwitchWithEnumerableGeri dönüş void, bu durum için zayıf bir tasarımdır. NEDEN: Birini if-elsebağımsız bir ifadeye dönüştürdünüz - bu da amacı gizliyor, yani birbirini dışlayan olmaları - yalnızca bir actiontanesi yürütüldü. Bunun yerine dönmek boolgövdeli, if (..) { action(); return true; } else return false;çağıran site sonra niyetini gösterir: if (MySwitchWithEnumerable(..)) else (MySwitchWithEnumerable(..));. Bu tercih edilir. Ancak, bu basit durum için artık orijinal sürümünüz üzerinde önemli bir gelişme de değildir.
ToolmakerSteve

15

İşte tam 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;
}

Çok dizeleri ile çalışır ...

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

Bu, dizileri her anahtar ifadesiyle ayırdığınız anlamına gelir, değil mi? Sabit değişkenlerimiz olsaydı daha iyi olmaz mıydı?
MaLiN2223

Zarif, ancak derleyicinin bu senaryoyu optimize edip etmediğini bilmek iyi olur, böylece tekrarlanan çağrılar dizi yapısının yükünü her seferinde ortaya çıkarmaz; dizileri önceden tanımlamak bir seçenektir, ancak zarafetin çoğunu ortadan kaldırır.
mklement0

11

Aşağıdaki kod irade değil işin:

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 kodu kolayca aralıkları koyabilirsiniz Visual Basic içinde çalışır ... deyimi veya uygun bloklar noneseçeneğinde , ben çok aşırı noktada, Visual Basic ile .dll yapmak ve geri almak öneririz C # projenize.switchif else

Not: Visual Basic'te anahtar eşdeğeri Select Case.


7

Başka bir seçenek rutin kullanmak olacaktır. Eğer 1-3 arası vakaların hepsi aynı mantığı çalıştırırsa, o mantığı rutin bir şekilde sarın ve her vaka için çağırın. Bunun aslında durum ifadelerinden kurtulmadığını biliyorum, ancak iyi bir stil uyguluyor ve minimum bakım gerektiriyor .....

[Düzenle] Orijinal soruyla eşleşen 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()
{
   ...
}

5

C # 'da daha az bilinen anahtar yönü , operatöre = bağlı olduğu ve geçersiz kılınabileceğinden şöyle bir şey olabilir:


string s = foo();

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

4
Bu daha sonra kod okumaya çalışan biri için büyük bir yaka olabilir
Andrew Harry

5

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üzenleme : Sadece soru üzerinde C # etiketi fark, bu yüzden muhtemelen bir gcc cevap yardımcı olmaz.


4

C # 7'de şimdi Desen Eşleme var, böylece şöyle bir şey yapabilirsiniz:

switch (age)
{
  case 50:
    ageBlock = "the big five-oh";
    break;
  case var testAge when (new List<int>()
      { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 }).Contains(testAge):
    ageBlock = "octogenarian";
    break;
  case var testAge when ((testAge >= 90) & (testAge <= 99)):
    ageBlock = "nonagenarian";
    break;
  case var testAge when (testAge >= 100):
    ageBlock = "centenarian";
    break;
  default:
    ageBlock = "just old";
    break;
}

3

Aslında GOTO komutunu da sevmiyorum, ancak resmi Microsoft malzemelerinde ve burada izin verilen sözdizimleri var.

Bir anahtar bölümünün deyim listesinin bitiş noktasına erişilebiliyorsa, derleme zamanı hatası oluşur. Bu, "düşme yok" 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 ulaşılabilir bir bitiş noktası olmadığı için 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 "düşmesine" izin verilmez ve örnek

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

derleme zamanı hatasına neden olur. Bir anahtar bölümünün yürütülmesinin ardından başka bir anahtar bölümünün yürütülmesinin ardından, açık bir goto vakası veya goto varsayılan ifadesi kullanılmalıdır:

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

Bir anahtar bölümünde birden çok 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 ve aslında düşmenin tek yolu bu.

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


Pratikte, gotoneredeyse her zaman önlenebilir (burada "korkunç" olarak düşünmese de - belirli, yapılandırılmış, rolü dolduruyor). Örneğinizde, vaka gövdelerini işlevlere (iyi bir şey) sarmaladığınız için, vaka 0 olabilir CaseZero(); CaseZeroOrOne(); break;. Gerek yok goto.
ToolmakerSteve

Bağlantı yarı kesik (yönlendirmeler, "Visual Studio 2003 Emekli Teknik belgeler" ).
Peter Mortensen

2

Bir şekilde daha iyi görünmek veya daha iyi çalışmak için C # en az kullanılan sözdizimlerinden birini almanın yollarını bulmak için çok fazla iş yapıldı. Şahsen ben anahtarı ifade nadiren kullanmaya değer buluyorum. Hangi verileri test ettiğinizi ve istediğiniz sonuçları analiz etmenizi şiddetle tavsiye ederim.

Diyelim ki, asal sayı olup olmadıklarını görmek için bilinen bir aralıktaki değerleri hızlı bir şekilde test etmek istiyorsunuz. Kodunuzun israflı hesaplamaları yapmasını önlemek istiyorsunuz ve çevrimiçi olarak istediğiniz aralıktaki primerlerin bir listesini bulabilirsiniz. Her bir değeri bilinen asal sayılarla karşılaştırmak için büyük bir anahtar deyimi kullanabilirsiniz.

Veya sadece bir dizi asal harita 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 dizedeki bir karakterin onaltılı olup olmadığını görmek istersiniz. Kanlı ve biraz büyük bir anahtar deyimi kullanabilirsiniz.

Veya char'ı test etmek için normal ifadeleri kullanabilir veya bilinen onaltılık harflerden oluşan bir dizede char'ı 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 bir değere bağlı olarak 3 farklı işlemden birini yapmak istediğinizi varsayalım. IF ifadelerinin bir kümesini kullanmanızı öneririm. Ve bu çok karmaşık hale gelirse (Veya sayılar 1 ila 90 aralığındaki bir değere bağlı olarak 5 farklı eylem gibi daha büyük olsaydı), eylemleri tanımlamak ve numaralandırmaların bir dizi haritasını oluşturmak için bir enum kullanın. Değer daha sonra dizi haritasına indekslemek ve istediğiniz eylemin numaralandırmasını almak için kullanılır. Ardından, elde edilen enum değerini işlemek için küçük bir IF deyimi kümesi veya çok basit bir switch deyimi kullanın.

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


Ayrıca lambda ifadesi veya bir temsilci ile eşleştirebilirsiniz
Conrad Frix

Güzel nokta. Küçük bir yorum: Genellikle belirli bir durumla eşleşen değerlerin bir listesini tutmak için bir dizi haritasından daha kolay buluyorum. Dizi haritası ile ilgili sorun bir hata yapmak kolay olmasıdır. Örneğin, true / false primer dizisi eşlemesi yerine, yalnızca bir primer listesine sahip olun ve arama performansı için bir HashSet'e yükleyin. İkiden fazla vaka olsa bile, genellikle bir vaka dışında tümü küçük bir listedir, bu nedenle diğer vakaların listelerinden bir HashSet sıralaması (seyrekse) veya kod halinde bir dizi haritası oluşturun.
ToolmakerSteve

1

Sadece görüşmeye eklemek için, .NET 4.6.2 kullanarak şunları da yapabildim. Kodu test ettim ve benim için çalıştı.

Aşağıdaki gibi birden çok "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;
            }

Ayrıca, bir 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;
            }

Bu, .NET sürümüne değil C # sürümüne bağlı değil mi?
Peter Mortensen

1

Aynı şeyi yapan çok büyük miktarda dizeler (veya başka bir tür) durumunuz varsa, string.Contains özelliği ile birlikte bir dize listesinin kullanılmasını öneririm.

Yani böyle büyük bir anahtar deyiminiz 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 aşağıdaki ifgibi bir ifadeyle 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, herhangi bir dizi dize durumu için iyi ölçeklendirilir.



-5

Bunun için bir goto ifadesi kullanırsınız. Gibi:

    switch(value){
    case 1:
        goto case 3;
    case 2:
        goto case 3;
    case 3:
        DoCase123();
    //This would work too, but I'm not sure if it's slower
    case 4:
        goto case 5;
    case 5:
        goto case 6;
    case 6:
        goto case 7;
    case 7:
        DoCase4567();
    }

7
@scone goto, prosedürel programlamanın temel prensibini (c ++ ve c # hala köklüdür; saf OO dilleri değildir (şükürler olsun)). Yordamsal programlama, dil yapıları ve yöntem çağırma kuralları (çalışma zamanı yığınının nasıl büyüdüğü ve küçüldüğü) tarafından belirlenen iyi tanımlanmış bir mantık akışına sahiptir. Goto ifadesi, temelde rastgele atlamaya izin vererek bu akışı atlatır.
samis

1
İyi bir tarz olduğunu söylemiyorum, zalim, ama asıl sorunun istediğini yapıyor.
çörek

2
Hayır, "asıl sorunun ne istediğini yapmaz". Orijinal soru, olduğu gibi çalışan bir kod vardı . Düzeltmeye ihtiyaçları yoktu. Ve öyle olsalar bile, bu korkunç bir öneri. Daha az özlü ve kullanır goto. Daha da kötüsü, gotoOP tarafından belirtilen orijinal sözdiziminin işe yaraması nedeniyle tamamen gereksiz bir kullanımdır . Soru, alternatif davaları vermenin daha özlü bir yolu olup olmadığıydı . İnsanların sizden yıllar önce cevap verdiği gibi , evet - birkaç örneği bir satıra koymaya istekli iseniz case 1: case 2:ve editörün otomatik stili izin veriyorsa.
ToolmakerSteve

Gitmenin kötü olarak belirlenmesinin tek nedeni, bazı insanların mantık akışını takip etmeyi zor bulmasıdır. Net MSIL (birleştirilmiş nesne kodu) hızlı olduğu için her yerde goto kullanır, ancak .Net kodu yazılabilir ve onlarsız performans gösterebilirse, bunları kullanmamak daha iyidir ve bu nedenle @ gibi kişiler tarafından alev almazsınız. Steve'in küçümseyen yanıtı.
dynamiclynk

@wchoward - Lütfen cevabımı daha dikkatli okuyun. Benim şikayet sadece goto kullanımı ile ilgili değildir . İtiraz ettim çünkü soru zaten olduğu gibi çalışan kod gösterdi ve bu cevap a) bu çalışma kodunu alıp daha ayrıntılı ve daha az iyi yapılandırılmış bir fayda sağlamaz hale getiriyor , b) soruyu cevaplamıyor.
ToolmakerSteve
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.