Bir switch ifadesi bir değeri sabit case etiketlerinden oluşan bir listeyle karşılaştırır ve eşleşen bölümü çalıştırır. C#'ta her bölüm break (ya da onu terk eden başka bir ifade) ile bitmelidir, bu yüzden bir case asla sessizce bir sonrakine geçemez.
Çıktı:
200: OK
302: redirect
404: not found
500: unhandled status
Parantez içindeki değer bir kez değerlendirilir ve her etiketle karşılaştırılır. default hiçbir şey eşleşmediğinde çalışır; isteğe bağlıdır ve listede herhangi bir yerde olabilir, ama genellikle en sona yazılır. Eşleşme ve default yoksa tüm switch hiçbir şey yapmaz.
Her Bölüm Bir break Gerektirir
C, C++, Java ve JavaScript'te break'i unutmak çalışmanın bir sonraki case'e kaymasına yol açar. C# bu hatayı bir derleme hatasına çevirir:
switch (level)
{
case 1:
Console.WriteLine("read");
// error CS0163: Control cannot fall through from one case label ('case 1:') to another
case 2:
Console.WriteLine("write");
break;
}
Kural şudur: bir bölümün ifade listesinin sonuna ulaşılabilmemelidir. Bunu sağlamanın olağan yolu break'tir, ama bölümü terk eden her şey çalışır:
returntüm metottan çıkar; küçük bir yardımcı içinde çoğu zaman en temiz biçimdir.throwhiç oluşmaması gereken bir değer için istisna fırlatır.continue,switchbir döngünün içindeyse sonraki yinelemeye atlar.goto casevegoto defaultbilerek başka bir bölüme atlar.
Son bölüm muaf değildir. En altta break olmayan bir default: CS8070, Control cannot fall out of switch from final case label ('default:') ile başarısız olur.
Tek Bir case'te Birkaç Değer
Aralarında ifade olmayan etiketler altlarındaki bölümü paylaşır. C#'ın izin verdiği tek düşüş türü budur, çünkü boş bir etiket hiçbir kodu gizleyemez:
Çıktı:
'O' is a vowel
'k' is a consonant or symbol
' ' is a space
'7' is a digit
Buradaki her bölüm return ile biter, bu yüzden break gerekmez (bir return'den sonraki break ulaşılamaz kod olurdu). Aynı değere sahip iki etiket bir hatadır, CS0152 The switch statement contains multiple cases with the label value '1', ve her etiket bir derleme zamanı sabiti olmalıdır: bir case içindeki değişken "a constant value is expected" ile başarısız olur.
String Üzerinde switch
String'ler tamsayılardan sonra en yaygın switch değeridir. Karşılaştırma ordinal ve harf duyarlıdır, bu yüzden switch'ten önce girdiyi normalleştirin:
Çıktı:
Starting the server
Stopping the server
Server is running
Unknown command: restart
Unknown command: (none)
ToLowerInvariant olmadan "STOP" default'a ulaşırdı. null bir değer üzerinde switch yapmak serbesttir: hiçbir string sabitiyle eşleşmez ve default'a düşer, bu yüzden switch'in kendisi asla istisna fırlatmaz.
Enum Üzerinde switch
switch enum'lar için yapılmıştır: kapalı bir adlandırılmış değerler kümesi.
Çıktı:
Pending: wait for payment
Paid: pack and ship
Shipped: track the parcel
Delivered: nothing, order is closed
Cancelled: nothing, order is closed
ArgumentOutOfRangeException for value 42
Derleyici bir switch ifadesinin her enum üyesini kapsayıp kapsamadığını kontrol etmez ve bir enum değişkeni, alttaki tipinin herhangi bir tamsayısını tutabilir ((OrderStatus)42 geçerlidir). İstisna fırlatan default, unutulmuş bir case'i sessiz bir hiçlik yerine anında, açık bir başarısızlığa çevirir.
goto case ve goto default
Bir case gerçekten diğerine devam etmesi gerektiğinde C# atlamayı yazmanızı ister:
Çıktı:
admin:
manage users
edit posts
read posts
editor:
edit posts
read posts
guest:
read posts
goto case, aynı switch'teki etiketlerden biriyle eşleşmesi gereken bir sabit alır. Gerçek kodda nadirdir: paylaşılan davranış genellikle birkaç case'in çağırdığı bir metot olarak daha anlaşılırdır. Yine de "C#'ta bir sonraki case'e nasıl düşülür" sorusunun cevabı budur.
case'lerin İçindeki Değişkenler
Tüm switch bloğu tek bir kapsamdır, bu yüzden iki case aynı adda bir değişken bildiremez:
switch (shape)
{
case "square":
int area = side * side;
break;
case "rectangle":
int area = width * height; // error CS0128: A local variable or function named 'area' is already defined in this scope
break;
}
Her bölümün gövdesini kendi kapsamını vermek için süslü parantez içine alın: case "square": { int area = side * side; ... break; }.
Döngü İçinde break
Bir case'teki break çevresindeki döngüden değil switch'ten çıkar. continue tersini yapar: bir switch döngü değildir, bu yüzden continue döngünün sonraki yinelemesine gider.
Çıktı:
end marker found
Total: 134
Döngü "end"'den sonra devam etti ve 99'u ekledi. Döngüyü bir switch'in içinden durdurmak için bir bayrak ayarlayıp switch'ten sonra test edin ya da döngüyü bir metoda taşıyıp return kullanın. break ve continue sayfası seçenekleri karşılaştırır.
Desen case Etiketleri ve when
C# 7.0'dan beri bir case etiketi sabit yerine bir desen olabilir: değerin tipini test edebilir ve bir when koşulu ekleyebilir. Bu biçim modern C# kodunda yaygındır:
static string Describe(object value)
{
switch (value)
{
case null:
return "nothing";
case int n when n < 0:
return $"negative int {n}";
case int n:
return $"int {n}";
case string s when s.Length == 0:
return "empty string";
case string s:
return $"string \"{s}\"";
default:
return $"other: {value.GetType().Name}";
}
}
Desenlerle sıra önemlidir: eşleşen ilk case kazanır ve daha önceki bir case onu zaten kapsadığı için hiç ulaşılamayacak bir case olduğunda derleyici hata bildirir (case int n:'i case int n when n < 0:'ın üstüne koymak başarısız olur). when cümlesi sabit case'lerde de çalışır: case 0 when isAdmin:. C# 9 ilişkisel ve mantıksal desenleri ekledi, böylece bir case case >= 90: ya da case 'a' or 'e' or 'i': şeklinde okunabilir.
Desensiz C# 7'de aynı tipe göre dağıtım, is tip deseniyle bir if zinciridir:
Çıktı:
negative int -3
int 12
empty string
string "hi"
other: Decimal
nothing
Bir switch'in her dalı yalnızca bir değer hesaplıyorsa switch expression daha da kısadır: var grade = score switch { >= 90 => "A", >= 80 => "B", _ => "C" };. Switch expression sayfası sözdizimini, desenlerini ve kapsayıcılık kurallarını ele alır.
Neyin Üzerinde switch Yapılabilir
| Değer tipi | Sabit case'ler | Notlar |
|---|---|---|
int, long, byte ve diğer tamsayılar | evet | klasik durum |
char | evet | case 'a': |
string | evet | ordinal, harf duyarlı, null default'a gider |
bool | evet | geçerli, ama bir if daha anlaşılır |
herhangi bir enum | evet | kapsayıcılık kontrolü yok |
double, decimal | C# 7'den itibaren | yalnızca sabitler; aralıklar C# 9 ilişkisel desenlerini gerektirir |
| diğer her tip | C# 7'den itibaren | tip desenleriyle, case Circle c: |
Sıkça Sorulan Sorular
C# switch'te break zorunlu mu?
Her case bölümü onu terk eden bir ifadeyle bitmelidir: genellikle break, ama return, throw, continue (bir döngü içinde) ya da goto case da sayılır. Bir bölümün sonundan sonrakine düşmek bir derleme hatasıdır, CS0163 Control cannot fall through from one case label ('case 1:') to another, ve buna son bölüm de dahildir.
Tek bir C# switch case'inde birden fazla değer nasıl ele alınır?
Etiketleri aralarına hiçbir şey koymadan üst üste yazın: case "sat": case "sun": Console.WriteLine("weekend"); break;. Boş case etiketleri sonraki etikete düşebilir; yalnızca ifade içeren bir bölüm break ile bitmek zorundadır. C# 9 ve sonrasında bir desen case'i case 1 or 2 or 3: de diyebilir.
C#'ta string üzerinde switch büyük/küçük harfe duyarlı mı?
Evet. String case'leri ordinal, harf duyarlı eşitlikle karşılaştırılır, bu yüzden "Yes" case "yes": ile eşleşmez. Değeri önce switch (input.Trim().ToLowerInvariant()) ile normalleştirin. null bir string hiçbir sabit case ile eşleşmez ve default'a gider.
C# switch, C ya da Java'daki gibi bir sonraki case'e düşebilir mi?
Örtük olarak hayır. Bir case'in diğerine devam etmesini istediğinizde bunu goto case <value>; ya da goto default; ile söyleyin. Bu, her düşüşü kodda görünür kılar; C#'ın sessiz sürümü yasaklamasının nedeni budur.
C#'ta switch ifadesi ile switch expression arasındaki fark nedir?
Bir switch ifadesi (statement) ifadeler çalıştırır ve case, break ve default gerektirir. Bir switch expression (C# 8 ve sonrası) bir değer üretir: var label = n switch { 0 => "zero", > 0 => "positive", _ => "negative" };. Her dal yalnızca bir sonuç hesaplıyorsa expression'ı kullanın.