Pattern Matching C# da yeni sayılabilecek bir özelliktir. İlk olarak C# 7.0 ile birlikte tanıtıldı ve 7.0 sonrasında ki tüm sürümlerde ek güncellemeler aldı. Bu yazımızda C# Pattern Matching kullanımını ve sürümler arasında ki gelişimlerini inceleyeceğiz.
Pattern Matching Nedir?
Pattern Matching, object tiplerin belirtilen bir tip olup olmadığını test edebileceğimiz veya belirtilen bir tipe eşleşme yapabilceğimiz bir ifade alma ve atama işlemidir. Daha kısa özetlemek gerekirse is operatörü kullanarak yapmış olduğumuz nesne eşleştirme işleminin pratik çözümüdür. Tüm pattern matching’lerin ortak özelliği Boolean eleşme/eşleşmeme özelliğidir. Diğer tüm pattern matching türleri bu eşleşme/eşleşmeme mantığı üzerine kurulmuştur.
Pattern Matching – C# 7.0
Constant Pattern
Constant pattern bir ifadenin belirtilen bir sabit değer ile eşleşip/eşleşmediğini test etmek için kullanırız. Constant pattern için popüler bir kullanım durumu null denetimdir. Bir tipin null olup olmadığını Constant Pattern ile kolay bir şekilde kontrol edebiliriz.
public class Program
{
private static void Main(string[] args)
{
Rectangle rectangle = new Rectangle() { Length=10, Height=5};
if (rectangle is null)
{
Console.WriteLine("Null Recatangle");
}
else
{
Console.WriteLine("Not Null Recatangle");
}
}
}
public class Rectangle
{
public double Length { get; set; }
public double Height { get; set; }
}
Sonuç:
Not Null Recatangle
Declaration Pattern
Declaration pattern, çalışma zamanında bir ifadenin belirli bir tiple eşleşip/eşleşmediğini kontrol etmek için kullanırız. Aşağıdaki örnekte Shape tipinin Square tipiyle eşleşip/eşleşmediğini kontrol ederiz.
public class Program
{
private static void Main(string[] args)
{
object shape = new Square() { Length = 5 };
if (shape is Square square)
{
Console.WriteLine("Şekil, bir kenar uzunluğu olan bir karedir." + square.Length);
}
else
{
Console.WriteLine(shape + " bir kare değildir.");
}
}
}
public class Square
{
public double Length { get; init; }
}
Sonuç:
Şekil, bir kenar uzunluğu 5 olan bir karedir.
Pattern Matching – C# 7.0
Property Pattern
Property modeli, property’lerin (özelliklerin) değerlerini kontrol etmek ve karşılaştırmak için kullanılır. Bir ifadenin properties/fields (özelliklerinin/alanlarının) belirtilen properties/fields (özelliklerin/alanların) değerleriyle eşleşip eşleşmediğini test eder. Karşılık gelen her property veya field eşleşmelidir ve ifade null olmamalıdır.
public class Program
{
private static void Main(string[] args)
{
Triangle triangle = new Triangle() { Base = 4, Height = 6 };
if (triangle is Triangle { Base: 4, Height: 6 } specificTriangle)
{
Console.WriteLine($"Şekil tabanı {specificTriangle.Base} ve yüksekliği {specificTriangle.Height} olan bir üçgendir");
}
}
}
public class Triangle
{
public double Base { get; init; }
public double Height { get; init; }
}
Sonuç:
Şekil tabanı 4 ve yüksekliği 6 olan bir üçgendir
Var Pattern
Var pattern, herhangi bir ifadeyi eşleştirmek ve ardından onu yeni bir değişkene atamak için kullanılır. Eşleştirme var tipi üzerinden yapıldığı için her zaman eşleşme sağlanacaktır. Bu nedenle diğer pattern’lardan farklıdır. Bir var pattern’ının amacı ifadeyi test etmek yerine yeni bir değişkene atamaktır. Özellikle hesaplamalar sırasında ara değerleri geçici bir değişkende depolamak istiyorsanız var pattern kullanışlıdır.
public class Program
{
private static void Main(string[] args)
{
object shape = new Rectangle { Length = 9, Height = 4 };
if (shape is Rectangle { Length: var length } rect && length % 3 == 0)
{
Console.WriteLine("Bu şekil, uzunluğu 3'ün katı olan bir dikdörtgendir");
}
}
}
public class Rectangle
{
public double Length { get; init; }
public double Height { get; init; }
}
Sonuç:
Bu şekil, uzunluğu 3'ün katı olan bir dikdörtgendir
Positional pattern
Positional pattern, Deconstruct (Yapısı çözülebilen) bir tipi test ederken kullanılır. Yapısı çözülebilenden kastım tipleri parçalara ayırma ve onları yeni değişkenlere depolama işlemidir. Örneğin, bir sınıf özelliklerine bölünebilir veya bir tuple, kendi bireysel öğelerine bölünebilir.
public class Program
{
private static void Main(string[] args)
{
Rectangle rectangle = new Rectangle { Length = 20, Height = 40 };
var (l, h) = rectangle;
if (rectangle is (20, _) rect)
{
Console.WriteLine("Dikdörtgenin uzunluğu 20");
}
}
}
public struct Rectangle
{
public double Length { get; init; }
public double Height { get; init; }
public void Deconstruct(out double length, out double height)
{
length = Length;
height = Height;
}
}
Sonuç:
Dikdörtgenin uzunluğu 20
Pattern Matching – C# 9.0
Relational pattern
Relational pattern, karşılaştırma operatörleri (>, <, >=, <=) kullanılarak bir değerin bir sabitle nasıl karşılaştırıldığını test ederek karşılaştırmalar için kullanılabilir.
public class Program
{
private static void Main(string[] args)
{
object shape = new Circle { Radius = 110 };
if (shape is Circle { Radius: >= 100 })
{
Console.WriteLine($"Büyük bir çember");
}
}
}
public class Circle
{
public double Radius { get; init; }
}
Sonuç:
Büyük bir çember
Type Pattern
Type pattern, declaration pattern gibi çalışma zamanında bir ifadenin belirli bir tipte olup olmadığını belirlemek için kullanılır.
public class Program
{
private static void Main(string[] args)
{
object shape = new Square { Length = 5 };
if (shape is Square)
{
Console.WriteLine($"{shape} bir kare");
}
else
{
Console.WriteLine($"{shape} bir kare değil");
}
}
}
public class Square
{
public double Length { get; init; }
}
Sonuç:
Square bir kare
Logical Pattern
C# 9.0 ayrıca, aşağıdaki logical pattern oluşturmak için pattern birleştiricileri kullanma yeteneği olan logical pattern’leri de tanıttı:
C# 9.0’dan önce, bir nesnenin null olup olmadığını kontrol etmek için aşağıdaki kod kullanılırdı:
if (shape != null)
C# 9.0’da logical paternkullanılarak bir nesnenin null olup olmadığını şu şekilde kontrol edebilirsiniz.
if (shape is not null)