Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

C# 11 – List and Slice Pattern

Merhaba,

Gün geçmiyor ki, C# yeteneklerine yeni bir nitelik kazandırmasın 🙂 Bu içeriğimizde, C# 11 ile gelen özellikler arasında nacizane olarak oldukça kullanışlı gördüğüm List Pattern üzerine odaklanacak ve gelen bu yeniliğin tüm özelliklerini değerlendiriyor olacağız.

List Pattern, elimizdeki List koleksiyonlarının ya da dizilerinin değerlerini farklı bir diziyle eşleştirebilmemizi ve bu eşleştirme neticesinde sonucu boolean olarak edinebilmemizi sağlayarak şartlı kodlarda üst düzey yaklaşım sergilememize olanak tanıyan bir yeniliktir.

Bu pattern’a dair daha detaylı konuşabilmek için öncelikle aşağıdaki örnekler üzerinden konuyu somutlaştırarak mevzuya girelim.

int[] array = { 1, 2, 3 };

Console.WriteLine(array is [1, 2, 3]);  //true
Console.WriteLine(array is [1]);        //false
Console.WriteLine(array is [1, 2]);     //false
Console.WriteLine(array is [3, 4, 5]);  //false

Yukarıdaki kod bloğunu incelerseniz eğer 1. satırda tanımlanan dizi(esasında bir koleksiyonda olabilirdi) alt satırlarda is operatörü eşliğinde farklı dizisel değerlerle karşılaştırılmakta ve sonuç boolean olarak elde edilmektedir.

İşte bu list pattern’ın ta kendisidir. Dikkat ederseniz, ilgili pattern’ı uygulayabilmek için köşeli parantezler [] semantik olarak bizlere eşlik etmektedir.

Bu şekilde bir kullanımla ilgili koleksiyonun kümülatif olarak verilen diziyle aynı olup olmadığı kontrol edilmektedir. Halbuki bizler koleksiyon içerisinde verilen değerlerin olup olmadığını yahut sıra gözetmeksizin farklı verilerin varlığını kontrol etmek isteyebiliriz. İşte böyle bir durumda aşağıdaki gibi discard operatöründen de istifade edebilmekteyiz.

int[] array = { 1, 2, 3 };

Console.WriteLine(array is [_, 2, _]);          //true
Console.WriteLine(array is [_, 1, _]);          //false
Console.WriteLine(array is [1, 2, _]);          //true
Console.WriteLine(array is [_, _, _, 3, 4, 5]); //false
Console.WriteLine(array is [_, _, _]);          //true

Görüldüğü üzere discard operatörü ile bir nebze koleksiyon verilerinin karşılaştırılmasında esneklik sağlamış olsak da hala değerlendirmenin sıralı bir şekilde olmasından kurtulabilmiş değiliz. Bunun için aşağıdaki gibi slice pattern’dan da faydalanabiliriz.

int[] array = { 1, 2, 3 };

Console.WriteLine(array is [_, .., 2, _]);      //true
Console.WriteLine(array is [1, 2, ..]);         //true
Console.WriteLine(array is [_, .., _, 3, 4, 5]);//false
Console.WriteLine(array is [_, _, _]);          //true
Console.WriteLine(array is [..]);               //true

Slice pattern’da kullanılan range operatörü sayesinde sıralamanın herhangi bir yerinde istenilen değere karşılık değerlendirme yapılabilir ya da kaynak koleksiyondaki veri sayısıyla/uzunluğuyla ilgilenilmediği taktirde yine bu range pattern’dan istifade edilebilir.

Bu arada unutulmamalıdır ki, slice pattern bir dizi içerisinde yalnızca tek bir kez kullanılmakta aksi taktirde derleyici hatası alınmaktadır.
C# 11 - List and Slice PatternEsasında şuana kadar yaptığımız tüm örneklendirmelerde list pattern içerisinde sabit değerler kullandığımızdan dolayı farkında olmadan constant pattern kullanmış bulunmaktayız. Normal şartlarda bu sabitliğe olan bağımlılığı değiştirebilir ve relational pattern gibi kalıpları da uygulayabiliriz.

int[] array = { 1, 2, 3 };

Console.WriteLine(array is [_, >= 2, < (3 * 5)]);   //true
Console.WriteLine(array is [_, .., < (3 * 5)]);     //true

Görüldüğü üzere list pattern, özellikle elimizdeki koleksiyonel verilerde yapı düzenini gözetmeksizin yapılacak karşılaştırmalarda oldukça etkili bir özelliktir. Nihayetinde elimizdeki koleksiyondan verileri bir objeye dönüştürme gereği duymaksızın direkt olarak bu pattern sayesinde hızlıca kontrollerimizi sağlayabilir ve operasyonlarımızı gerçekleştirebiliriz.

Şimdi son olarak Microsoft’un dökümanlarında(bknz : list patterns) konuya dair oldukça güzel bir örneği burada modelleyip ardından içeriğimizi sonlandıralım istiyorum.

Bir bankada, herhangi bir müşterinin belirli tarihler aralığındaki işlem bilgilerini içeren metin dosyasının aşağıdaki şekilde alıntılandığını varsayalım.

Tarih İşlem Açıklama Kime Ücret
18.05.2022 FAST Deposito ödeme Hilmi Celayir 1500₺
12.05.2022 FAST Apartman aidat Faruk Eczaneci 50₺
10.05.2022 EFT Mutfak dolabı taksidi 1050₺
09.05.2022 EFT Sigorta ödemesi 850₺
09.05.2022 FAST Köy sandığı Cemil Yılmaz 50₺

Yukarıdaki veri kümesine göz atarsanız eğer ilgili müşterinin yaptığı tüm para transferlerini görmekteyiz. Burada para transferini gerçekleştiren müşterimiz ise transferin gerçekleştirildiği kişinin ‘Kime’ kolonunda ismi yazılıyorken, dışarıdan müşteriye gerçekleştiriliyorsa eğer o zaman boş bırakılmakta, herhangi bir veri yazılmamaktadır. Para transferi sürecinde ‘FAST’te %2, ‘EFT’de ise %3 komisyon alındığını varsayarsak eğer böyle bir veri kümesi üzerinde list pattern eşliğinde, discard pattern, constant pattern ve var pattern‘ı aşağıdaki gibi kullanıp toplam bakiyeyi aşağıdaki gibi hesaplayabiliriz.

object[] bankProcess1 = { "18.05.2022", "FAST", "Deposito ödeme", "Hilmi Celayir", 1500 };
object[] bankProcess2 = { "12.05.2022", "FAST", "Apartman aidat", "Faruk Eczaneci", 50 };
object[] bankProcess3 = { "10.05.2022", "EFT", "Mutfak dolabı taksidi", 1050 };
object[] bankProcess4 = { "09.05.2022", "EFT", "Sigorta ödemesi", 850 };
object[] bankProcess5 = { "09.05.2022", "FAST", "Köy sandığı", "Cemil Yılmaz", 50 };

List<object[]> bankProcesses = new() { bankProcess1, bankProcess2, bankProcess3, bankProcess4, bankProcess5 };

float balance = 0;
foreach (object[] bankProcess in bankProcesses)
{
    balance += bankProcess switch
    {
        [_, "FAST", _, _, int amount] => -(amount + (amount * 2 / 100)),
        [_, "EFT", _, _, int amount] => -(amount + (amount * 3 / 100)),
        [_, "FAST", .., int amount] => amount,
        [_, "EFT", .., int amount] => amount,
        _ => 0
    };
}
Console.WriteLine($"Bakiye : {balance}");

C# 11 - List and Slice PatternAyrıca list pattern’ı var pattern ile birlikte aşağıdaki gibi kullanıp adedi bilinmeyen tüm verileri ayrı bir dizi olarak elde edebilmekteyiz.

var array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
if (array is [1, 2, .. var vals, 9])
    Console.WriteLine(String.Join(",", vals));

C# 11 - List and Slice PatternYukarıdaki kaynak koda göz atarsanız eğer .. var vals şeklinde iki pattern’ı kombinlersek eğer bizlere aralıktaki tüm değerleri dizi olarak getirecektir.

Nihai olarak,
Görüldüğü üzere list pattern’ı koleksiyonel veriler üzerinde dizisel eşleştirme verileriyle gönül rahatlığıyla kullanabilir ve kodunuza esneklik kazandırabilirsiniz.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Bunlar da hoşunuza gidebilir...

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.