Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Desen eşleştirme , bir ifadenin belirli özelliklere sahip olup olmadığını belirlemek için test ettiğiniz bir tekniktir. C# desen eşleştirmesi, ifadeleri test etme ve bir ifade eşleştiğinde eylem gerçekleştirme için daha kısa söz dizimi sağlar. "is
ifade", bir ifadeyi test etmek ve bu ifadenin sonucuna koşullu olarak yeni bir değişken bildirmek için desen eşleştirmeyi destekler. "switch
ifade", bir ifade için ilk eşleşen desene göre eylemler gerçekleştirmenizi sağlar. Bu iki ifade zengin desen kelime dağarcığını destekler.
Bu makalede, desen eşleştirmeyi kullanabileceğiniz senaryolara genel bir bakış sağlanır. Bu teknikler kodunuzun okunabilirliğini ve doğruluğunu geliştirebilir. Uygulayabileceğiniz tüm desenler hakkında tam bir tartışma için dil referansındaki desenler makalesine bakın.
Null denetimler
Desen eşleştirme için en yaygın senaryolardan biri, değerlerin olmadığından null
emin olmaktır. Aşağıdaki örneği kullanarak, null
kontrol ederken null atanabilir bir değer türünü test edebilir ve temel türüne dönüştürebilirsiniz:
int? maybe = 12;
if (maybe is int number)
{
Console.WriteLine($"The nullable int 'maybe' has the value {number}");
}
else
{
Console.WriteLine("The nullable int 'maybe' doesn't hold a value");
}
Yukarıdaki kod, değişkenin türünü test etmek ve yeni bir değişkene atamak için kullanılan bir bildirim desenidir. Dil kuralları bu tekniği diğerlerinden daha güvenli hale getirir. Bu değişkene number
yalnızca if
yan tümcesinin gerçek bölümünde ulaşılabilir ve atanır. Başka bir yerde, else
koşulunun içinde veya if
bloğundan sonra erişmeye çalışırsanız, derleyici bir hata verir. İkincisi, ==
işlecini kullanmadığınızdan, bir tür ==
işlecini aşırı yüklediğinde bu desen çalışır. Bu, null başvuru değerlerini denetlemek için ideal bir yoldur ve deseni not
ekler:
string? message = ReadMessageOrDefault();
if (message is not null)
{
Console.WriteLine(message);
}
Önceki örnekte, değişkeni ile karşılaştırmak için sabit bir desen kullanılmıştır.
not
, olumsuzlanan desen eşleşmediğinde eşleşen bir mantıksal desendir.
Tür testleri
Desen eşleştirme için bir diğer yaygın kullanım, bir değişkenin belirli bir türle eşleşip eşleşmediğini görmek için test etmektir. Örneğin, aşağıdaki kod bir değişkenin null olup olmadığını test eder ve arabirimini System.Collections.Generic.IList<T> uygular. Eğer varsa, listedeki ICollection<T>.Count özelliğini kullanarak ortadaki dizini bulur. Bildirim deseni, değişkenin derleme zamanı türünden bağımsız olarak bir null
değerle eşleşmiyor. Bu kod, null
için koruma sağladığı gibi, IList
uygulamayan bir türe karşı da koruma sağlar.
public static T MidPoint<T>(IEnumerable<T> sequence)
{
if (sequence is IList<T> list)
{
return list[list.Count / 2];
}
else if (sequence is null)
{
throw new ArgumentNullException(nameof(sequence), "Sequence can't be null.");
}
else
{
int halfLength = sequence.Count() / 2 - 1;
if (halfLength < 0) halfLength = 0;
return sequence.Skip(halfLength).First();
}
}
Aynı testler, bir switch
değişkeni birden çok farklı türe karşı test etmek için bir ifadeye uygulanabilir. Belirli bir çalışma zamanı türüne göre daha iyi algoritmalar oluşturmak için bu bilgileri kullanabilirsiniz.
Ayrık değerleri karşılaştırma
Belirli değerlerde eşleşme bulmak için bir değişkeni de test edebilirsiniz. Aşağıdaki kod, bir değeri bir sabit listesi içinde bildirilen tüm olası değerlerle test ettiğiniz bir örneği gösterir:
public State PerformOperation(Operation command) =>
command switch
{
Operation.SystemTest => RunDiagnostics(),
Operation.Start => StartSystem(),
Operation.Stop => StopSystem(),
Operation.Reset => ResetToReady(),
_ => throw new ArgumentException("Invalid enum value for command", nameof(command)),
};
Önceki örnekte, bir numaralandırmanın değerine göre bir yöntem gönderimi gösterilmektedir. Son _
durum, tüm değerlerle eşleşen bir atma düzenidir. Değerin tanımlı enum
değerlerden biriyle eşleşmediği tüm hata koşullarını işler. Bu anahtar kolunu atlarsanız, derleyici desen ifadenizin tüm olası giriş değerlerini işlemediği konusunda uyarır. Çalışma zamanında, switch
ifadesi incelenen nesne herhangi bir switch koluyla eşleşmezse bir istisna fırlatır. Enum değerleri kümesi yerine sayısal sabitler kullanabilirsiniz. Komutları temsil eden sabit dize değerleri için de bu benzer tekniği kullanabilirsiniz:
public State PerformOperation(string command) =>
command switch
{
"SystemTest" => RunDiagnostics(),
"Start" => StartSystem(),
"Stop" => StopSystem(),
"Reset" => ResetToReady(),
_ => throw new ArgumentException("Invalid string value for command", nameof(command)),
};
Yukarıdaki örnek aynı algoritmayı gösterir, ancak sabit listesi yerine dize değerlerini kullanır. Uygulamanız normal bir veri biçimi yerine metin komutlarına yanıt verirse bu senaryosunu kullanırsınız. C# 11'den başlayarak, sabit dize değerlerini test etmek için bir Span<char>
veya bir ReadOnlySpan<char>
kullanabilirsiniz, aşağıdaki örnekte gösterildiği gibi.
public State PerformOperation(ReadOnlySpan<char> command) =>
command switch
{
"SystemTest" => RunDiagnostics(),
"Start" => StartSystem(),
"Stop" => StopSystem(),
"Reset" => ResetToReady(),
_ => throw new ArgumentException("Invalid string value for command", nameof(command)),
};
Tüm bu örneklerde, göz ardı etme deseni her girişi işlemenizi sağlar. Derleyici, olası her giriş değerinin işlendiğinden emin olarak size yardımcı olur.
İlişkisel desenler
Bir değerin sabitlerle karşılaştırmasını test etmek için ilişkisel desenler kullanabilirsiniz. Örneğin, aşağıdaki kod Fahrenheit'teki sıcaklığa göre su durumunu döndürür:
string WaterState(int tempInFahrenheit) =>
tempInFahrenheit switch
{
< 32 => "solid",
32 => "solid/liquid transition",
(> 32) and (< 212) => "liquid",
212 => "liquid / gas transition",
> 212 => "gas",
};
Yukarıdaki kod, her iki ilişkisel desenin de eşleştiklerini denetlemek için konjonktif and
mantıksal deseni de gösterir. Ayrıca, her iki desenin de biriyle eşleşip eşleşmediğini kontrol etmek için ayrık desen yapısını kullanabilirsiniz. İki ilişkisel desen parantez içindedir ve netlik için herhangi bir desenin etrafında kullanabilirsiniz. İki belirgin anahtar kolu (32°F ve 212°F) erime noktası ve kaynama noktası durumlarını işler. Bu iki kol olmadan, derleyici mantığınızın olası her girişi kapsamadığı konusunda sizi uyarır.
Yukarıdaki kod, derleyicinin desen eşleştirme ifadeleri için sağladığı başka bir önemli özelliği de gösterir: Her giriş değerini işlemezseniz derleyici sizi uyarır. Derleyici ayrıca, bir anahtar kolu deseni önceki bir desen kapsamındaysa bir uyarı da sağlar. Bu sayede switch ifadelerini yeniden düzenleme ve sıralama özgürlüğüne kavuşursunuz. Aynı ifadeyi yazmanın başka bir yolu da şu olabilir:
string WaterState2(int tempInFahrenheit) =>
tempInFahrenheit switch
{
< 32 => "solid",
32 => "solid/liquid transition",
< 212 => "liquid",
212 => "liquid / gas transition",
_ => "gas",
};
Yukarıdaki örnekteki temel ders ve diğer tüm yeniden düzenleme veya yeniden sıralama işlemleri, derleyicinin kodunuzun tüm olası girişleri işlediğini doğrulamasıdır.
Birden çok giriş
Şimdiye kadar ele alınan tüm desenler tek bir girişi kontrol ediyor. Bir nesnenin birden çok özelliğini inceleyen desenler yazabilirsiniz. Aşağıdaki Order
kaydı göz önünde bulundurun:
public record Order(int Items, decimal Cost);
Yukarıdaki konumsal kayıt türü, açık konumlarda iki üyeyi bildirir. Önce Items
öğesi, ardından siparişin Cost
öğesi görünür. Daha fazla bilgi için bkz . Kayıtlar.
Aşağıdaki kod, indirimli fiyatı hesaplamak için madde sayısını ve siparişin değerini inceler:
public decimal CalculateDiscount(Order order) =>
order switch
{
{ Items: > 10, Cost: > 1000.00m } => 0.10m,
{ Items: > 5, Cost: > 500.00m } => 0.05m,
{ Cost: > 250.00m } => 0.02m,
null => throw new ArgumentNullException(nameof(order), "Can't calculate discount on null order"),
var someObject => 0m,
};
İlk iki kol, Order
öğesinin iki özelliğini inceler. Üçüncüsü ise yalnızca maliyeti inceler. Sonraki kontroller null
ile yapılır, ve son kontrol diğer tüm değerlerle eşleşir.
Order
Türü uygun Deconstruct
bir yöntem tanımlıyorsa, desenden özellik adlarını atlayabilir ve özellikleri incelemek için yapısızlaştırmayı kullanabilirsiniz:
public decimal CalculateDiscount(Order order) =>
order switch
{
( > 10, > 1000.00m) => 0.10m,
( > 5, > 50.00m) => 0.05m,
{ Cost: > 250.00m } => 0.02m,
null => throw new ArgumentNullException(nameof(order), "Can't calculate discount on null order"),
var someObject => 0m,
};
Önceki kod, ifade için özelliklerin çözümlendiği konumsal deseni gösterir.
Ayrıca, bir özelliği null olmayan herhangi bir değerle eşleşen { }
ile eşleştirebilirsiniz. Ölçümleri isteğe bağlı bir ek açıklamayla depolayan aşağıdaki bildirimi göz önünde bulundurun:
public record class Observation(int Value, string Units, string Name)
{
public string? Annotation { get; set; }
}
Aşağıdaki desen eşleştirme ifadesini kullanarak belirli bir gözlemde null olmayan bir ek açıklama olup olmadığını test edebilirsiniz:
if (observation.Annotation is { })
{
Console.WriteLine($"Observation description: {observation.Annotation}");
}
Liste şablonları
Liste deseni kullanarak bir listedeki veya dizideki öğeleri de kontrol edebilirsiniz. Liste düzeni , bir dizinin herhangi bir öğesine desen uygulamak için bir yol sağlar. Ayrıca, herhangi bir öğeyi eşleştirmek için atma desenini (_
) uygulayabilir veya sıfır veya daha fazla öğeyi eşleştirmek için bir dilim deseni uygulayabilirsiniz.
Liste desenleri, veriler normal bir yapıyı izlemediğinde değerli bir araçtır. Verilerin şeklini ve değerlerini bir nesne kümesine dönüştürmek yerine test etmek için desen eşleştirmeyi kullanabilirsiniz.
Banka işlemlerini içeren bir metin dosyasından aşağıdaki alıntıyı göz önünde bulundurun:
04-01-2020, DEPOSIT, Initial deposit, 2250.00
04-15-2020, DEPOSIT, Refund, 125.65
04-18-2020, DEPOSIT, Paycheck, 825.65
04-22-2020, WITHDRAWAL, Debit, Groceries, 255.73
05-01-2020, WITHDRAWAL, #1102, Rent, apt, 2100.00
05-02-2020, INTEREST, 0.65
05-07-2020, WITHDRAWAL, Debit, Movies, 12.57
04-15-2020, FEE, 5.55
Bu bir CSV biçimidir, ancak bazı satırlarda diğerlerinden daha fazla sütun vardır. İşleme açısından daha da kötü olan, WITHDRAWAL
türündeki bir sütun kullanıcı tarafından oluşturulan metin içeriyor ve bu metinde virgül bulunabilir.
Değer işleme verilerini bu biçimde yakalamak için atma desenini, sabit desenini ve var desenini içeren bir liste deseni:
decimal balance = 0m;
foreach (string[] transaction in ReadRecords())
{
balance += transaction switch
{
[_, "DEPOSIT", _, var amount] => decimal.Parse(amount),
[_, "WITHDRAWAL", .., var amount] => -decimal.Parse(amount),
[_, "INTEREST", var amount] => decimal.Parse(amount),
[_, "FEE", var fee] => -decimal.Parse(fee),
_ => throw new InvalidOperationException($"Record {string.Join(", ", transaction)} is not in the expected format!"),
};
Console.WriteLine($"Record: {string.Join(", ", transaction)}, New balance: {balance:C}");
}
Yukarıdaki örnek, her öğenin satırda bir alan olduğu bir dize dizisi alır. İkinci switch
alandaki ifade anahtarları, işlem türünü ve kalan sütunların sayısını belirler. Her satır, verilerin doğru biçimde olmasını sağlar. Atma deseni (_
), işlem tarihini içeren ilk alanı atlar. İkinci alan, hareket türüyle eşleşir. Kalan öğe ile eşleşen, tutarın bulunduğu alana atlar. Son eşleşme, miktarın dize gösterimini yakalamak için var desenini kullanır. İfade, bakiyenin ekleneceği veya çıkarleneceği miktarı hesaplar.
Liste desenleri , veri öğeleri dizisinin şekliyle eşleşmenizi sağlar. Öğelerin konumuna eşleşmek için discard ve slice desenlerini kullanırsınız. Tek tek öğelerle ilgili özellikleri eşleştirmek için başka desenler kullanırsınız.
Bu makalede, C# dilinde desen eşleştirme ile yazabileceğiniz kod türlerine ilişkin bir tur sağlanmıştır. Aşağıdaki makalelerde senaryolardaki desenleri kullanma örnekleri ve kullanılabilecek desenlerin tam sözlüğü gösterilmektedir.
Ayrıca bkz.
- 'is' denetimini takip eden bir dönüştürmeyi önlemek için desen eşleştirmeyi kullanın (stil kuralları IDE0020 ve IDE0038)
- Araştırma: Daha iyi kod için sınıf davranışınızı oluşturmak için desen eşleştirmeyi kullanma
- Öğretici: Tür temelli ve veri temelli algoritmalar oluşturmak için desen eşleştirmeyi kullanma
- Referans: Desen eşleştirme