C# 7.0 – Pattern Matching
Merhaba,
Bu içeriğimizde C# 7.0 sürümünün en gözde yeniliği olan Pattern Matching özelliği üzerinde duracağız. Detaya girmeden bahsetmek istiyorum ki, bir çok yazılımcı dostumunda beğenerek karşıladığı bu yenilik şahsen 7.0 versiyonu içerisinde diğerlerine nazaran en kullanışlı, en pratik ve en kazançlı bir özellik teşkil etmektedir. Detaylandırdıktan sonra anlaşılacaktır ki, hem gramersel hem de işlevsel olarak bu sürümün mavi boncuğunu hak etmiştir diyebiliriz. Tabi bu nazardan sonra başına ne gelebilir onuda merak etmedim değil 🙂 Neyse hadi gelin şimdi Pattern Matching özelliğinin sırrına vakıf olalım…
Bu özellik temelde tip sorgulama işlemlerinde bizlere pratiklik kazandırma esasına dayanmaktadır. Biliyorsunuz ki, bizler elimizdeki object tiplerin içindeki verileri yahut base class olan yapılar tarafından refere edilmiş nesnelerin tiplerini “is” operatörü tarafından tespit edebilmekteyiz.
Hazır lafını etmişken şöyle “is” operatörünün kullanımını aşağıya alalım.
static void Main(string[] args)
{
object x = 125;
if (x is string)
{
string xx = x as string;
Console.WriteLine($"x değişkeni string tipindedir.");
}
else if (x is int)
{
int xx = (int)x;
Console.WriteLine($"x değişkeni int tipindedir.");
}
Console.Read();
}
Görüldüğü üzere is operatörünü bu şekilde kullanarak verimizin tipini belirlemekte ve “as” yahut “cast” operatörleri aracılığıyla ilgili değer kendi tipinde object içerisinden elde edilmektedir.
İşte burada yapmış olduğumuz önce tip kontrolü(is) ardından ilgili tipte veriyi elde etme(as) işlemleri fazladan kod ve scope yazmamıza sebep olmakta ve kompleks bir çalışma tezahür ettirmektedir. Haliyle Pattern Matching özelliğiyle birazdan göreceğiniz yöntem(ler) sayesinde bu tarz durumlara oldukça pratik ve sade bir çözüm getirilmiştir.
Pattern Matching, bu ve bunun gibi durumlarda kullanacağımız, işimizi kolaylaştırmak ve pratik bir kod inşası sağlamak için desenleri aşağıdaki dört kategoride toplamıştır;
-
Type Pattern
Type Pattern ile yukarıda yaptığımız örneklendirmede olduğu gibi bir referans yahut object içerisindeki tipin belirlenmesi desenleştirilmiştir. Yani kısaca tip belirlemede kullanacağımız tasarımdır.Type Pattern’den önce,
static void Main(string[] args) { object x = 125; if (x is string) { string xx = x as string; Console.WriteLine($"x değişkeni string tipindedir."); } else if (x is int) { int xx = (int)x; Console.WriteLine($"x değişkeni int tipindedir."); } Console.Read(); }Type Pattern’den sorna,
static void Main(string[] args) { object x = 125; if (x is string xx) Console.WriteLine($"x değişkeni string tipindedir."); else if (x is int xx) Console.WriteLine($"x değişkeni int tipindedir."); Console.Read(); }Görüldüğü üzere “[referans] is [tip] [değisken]” kalıbındaki [değişken] kısmı “is” kontrolünün doğruluğunda ilgili referansı kontrol edilen tipte bize getirmektedir. Yani uzun uzun “as” yahut “cast” operatörleriyle yaptığımız dönüşümü arkaplanda yaptığını ve bu dönüşüm sonucunu ilgili tipte [değişken]’e verdiğini düşünün. Bir başka deyişle ilgili referans ilgili tiple eşleştirildiğinde otomatik olarak o tipte veri değişkenle elde edilmektedir.
-
Constant Pattern
Elimizdeki veriyi bir sabit değer ile karşılaştırabiliyoruz.Örneğin;
static void Main(string[] args) { object x = 125; if (x is 128) Console.WriteLine($"x değişkeninin değeri 128"); else if (x is 125) Console.WriteLine($"x değişkeninin değeri 125"); else if (x is 120) Console.WriteLine($"x değişkeninin değeri 120"); Console.Read(); }Bu şekilde kodumuzu çalıştırırsak çıktı olarak “x değişkeninin değeri 125” ifadesini verecektir.
Bir başka örnek;
static void Main(string[] args) { object x = "Gençay Yıldız"; if (x is "Gençay") Console.WriteLine($"Gençay"); else if (x is null) Console.WriteLine($"null"); Console.Read(); }Görüldüğü üzere null kontrolüde sağlayabiliyoruz.
-
Var Pattern
Eldeki veriyi “var” değişken tipiyle elde etmemizi sağlayan desendir. Hemen aşağıdaki örneği inceleyiniz.
static void Main(string[] args) { object x = "Türkiye"; if (x is var a) { Console.WriteLine(a); } Console.Read(); }Burada “x” değişkenini “var” ile elde edilerek “a” değişkenine atanmakta, haliyle aşağıdaki ekran görüntüsünde de görüldüğü gibi “a” değişkeninin tipi derleme aşamasında değil Run Time(Çalışma Zamanında)’da belirlenmektedir.

-
Recursive Pattern
Sıra geldi benim favorim olan desene 🙂 Bu desen switch – case yapısı üzerinde birçok yenilik getirmektedir.
Bu yenilikler;
- Artık tüm tipler switch – case yapısında kullanılabilecek.
- case – break bloklarında yukarıda anlatılan tüm desenler uygulanabilmektedir.
- case komutlarına çeşitli condition(şart, koşul) verilebilmektedir.
Şimdi aşağıdaki kod bloğunu inceleyiniz.
static void X(ICloneable instance) { switch (instance) { case SqlConnection connection: connection.ConnectionString = "Server=.;Database..."; break; case SqlCommand command when (command.Connection.ConnectionString == "Server=.;Database..."): command.CommandText = "Select * from..."; break; case StreamWriter stream: stream.Write("..."); break; case null: break; } }Dikkat ederseniz, switch bloğuna referans tipli bir değişken verilmiştir ve bu değişkenin refere ettiği nesnenin tipini case bloğunda sorgulayarak herhangi bir eşleşme durumunda “connection”, “command” yahut “stream” isimleri verilen değişkenler aracılığıyla ilgili nesneyi o ilgili tipte elde ediyoruz. Ayrıca when komutu ile verilen condition sağlandığı vakit ilgili case – break bloğu tetiklenecektir.
Recursive Pattern içerisinde referansların gösterdikleri nesnelerin tiplerini belirlediğimiz için Type Pattern ve null kontrolü sağladığımız içinde Constant Pattern kullanabilmekteyiz.
Gördüğünüz gibi Pattern Matching özelliği oldukça taktire şayan bir yeniliktir. Bizleri nasıl bir zahmet ve kod karmaşasından kurtardığına şahit olduk sanırım. Anlaşılan makalemizin sonuna geldik ama size güzel bir haber vererek konumuzu noktalamak istiyorum. Microsoft, Pattern Matching özelliği için süreçte daha çok geliştirileceğini ve bu özellik çerçevesinde daha fazla yenilik veya desen geleceğini bildirmekte ve ucu açık olarak konuyu hafızalara kazımaktadır.
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

1 Cevap
[…] Matching’ler ilk olarak C# 6.0’da tanıtıldılar ve ardından C# 7.0’da(bknz : C# 7.0 – Pattern Matching) daha da geliştirildiler ve C# 8.0’da(bknz : C# 8.0 – Switch Expression(Property – Tuple […]