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

C# 10 – Record Structs

Merhaba,

Bu içeriğimizde C# 9.0 ile hayatımıza giren record yapısının C# 10 ile gelen record structs isimli yeni özelliği üzerine incelemede bulunuyor olacağız.

Her şeyden önce record yapısının ne olduğunu hatırlatan girizgâhla başlayalım. Record’lar; verisel olarak değeri ön planda tutan, değerleri değiştirilemeyen ve compile neticesinde IEquatable<T>‘ı implemente ederek özünde bir sınıfa dönüşen referans türlü veri yapılarıdır. Record’ların ne olduğunu tam teferruatlı anlayabilmek için önceden klavyeye aldığım C# 9.0 – Records İle Immutable Datalar başlıklı makalemi baştan sona okumanızı ve ardından bu içeriğe göz atmanızı tavsiye ederim.

Record struct nedir? diye sorarsanız eğer; record’ın birçok avantajını sağlayan lakin değer türlü olması gibi radikal farkları olan veri yapılarıdır. Şimdi gelin record struct’ın ne olduğu, record’lardan farklarının neler olduğu şeklinde sualleri tek tek irdeleyerek cevap bulmaya çalışalım.

Record Struct Nasıl Oluşturulur?

Record struct’lar aynen bir struct gibi bir record gibi aşağıdaki semantikte oluşturulmaktadırlar.

Prototip :

record struct [name]
{
    ...
}

Misal olarak bir ‘Product’ record struct’ı aşağıdaki gibi oluşturulabilmektedir.

record struct Product
{
    ...
}

Eğer ki ‘Product’ record oluşturmak isteseydik aşağıda görüldüğü üzere bunun çok fazla semantik bir farkı bulunmayacaktı :

record Product
{
    ...
}

Tabi hazır lafı geçmişken söylemekte fayda var ki, C# 9.0 ile gelen bu record [name] yapılanması C# 10 ile record class [name] olarak da tanımlanabilmektedir.

record class Product
{
    ...
}

Bu tanımlama nihai olarak record ile record struct arasındaki karışıklılığı önlemek için zahiren daha uygun bir görsellik sağlamaktadır kanaatindeyim. Siz ne düşünüyorsunuz?

Velhasıl,

Nasıl ki bir record(ya da record class) tüm sınıf özelliklerine sahip olan bir sınıfsa aynı mantıkta bir record struct’ta özünde yine bir struct olan ve struct’ların tüm özelliklerine sahip olan yapılanmadır.

Bu iki record yapılanmasının aralarında benzerlikleri olduğu gibi davranışsal olarak temel farkları da mevcuttur. Şimdi gelin bu iki yapıyı tek tek özellikler çerçevesinde mukayese ederek farklarını ve benzerliklerini inceleyelim.

  • Immutability
    Biliyorsunuz ki record’lar da(ya da record class’lar da) Positional Records dediğimiz aşağıdaki özellik mevcuttur :

    record Person(string Name, string Surname)
    {
    
    }
    

    Positional records yapılanmasının en önemli kritiği değiştirilemez olmalarıdır.

    Person p = new Person("Gençay", "Yıldız");
    p.Name = "";
    

    Haliyle yukarıdaki kullanım hata verecektir. Bu kullanımdaki durumun nedenini önceki satırlarda referans ettiğim record’lara dair olan makalemdeki konuya dair olan paragrafı alıntılayarak izah etmek istiyorum.

    …bu property’ler default ‘init’ olacak şekilde oluşturulmakta ve nesne üretimi esnasında constructor’dan verilecek değerlerden sonra readonly olarak kullanılmaktadır….

    Amma velakin positional records özelliği record structs’ta kullanılıyorsa eğer değiştirilemez değildir!

    record struct Person(string Name, string Surname)
    {
    
    }
    

    Dolayısıyla bu durumda aşağıdaki kullanım hata vermeyecektir!

    Person p = new Person("Gençay", "Yıldız");
    p.Name = "";
    

    Bunun nedeni ise positional records’ların record struct’lar için oldukça farklı bir nitelik olmasıdır. Evet, görsel ve semantik açıdan tanımlanan record struct’tın constructor’ını oluşturmaya gerek kalmaksızın direkt olarak nesne oluşturma sürecinde record’lar da olduğu gibi set edilebilir property’ler tanımlamamızı sağlamaktadır belki ama kullanım açısından readonly ve ‘init’ olmayacak şekilde tanımlamaktadır. Eğer ki record struct’larda da positional records’ı değiştirilemez olarak kullanmak istiyorsanız readonly keywordünü aşağıdaki gibi kullanmanız gerekiyor.

    readonly record struct Person(string Name, string Surname)
    {
    
    }
    

    Haliyle bu şekilde bir tanımlama neticesinde artık ilgili property’ler aşağıdaki gibi değiştirilmeye kalkılınca hata verecektir.
    C# 10 - Record Structs

  • with Expressions
    with expressions, immutable tür olan record nesneleri üzerinde verisel değişiklik yapamadığımız için ilgili nesneyi klonlayarak(deep copy) istediğimiz yeni değerlerde yeniden oluşturmamızı sağlayan bir özelliktir. Haliyle record class’lar da olduğu gibi record struct’lar da with expressions niteliği kullanılabilmektedir.

    Person p = new Person("Gençay", "Yıldız");
    var newPerson = p with { Name = "Nevin" };
    
  • Equality Comparison(Eşitlik Karşılaştırması)
    C# 10 - Record StructsNormal şartlarda struct veri türleri üzerinde eşitlik(==) ve eşit değillik(!=) operatörleri yandaki görselde olduğu gibi desteklenmemektedir.

    Lakin konumuzla ilgili radikal değişikliklerden biriside bu ilgili operatörlerin record struct’lar tarafından desteklenmesidir. Aşağıdaki ekran alıntısını incelerseniz eğer ilgili operatörler record struct üzerinde kullanılabilmektedir.
    C# 10 - Record StructsTabi burada dikkat edilmesi gereken husus şudur ki, hatırlarsanız eğer record class’lar da verisel değerler ön planda tutulduğu için aynı değerlere sahip iki farklı record nesnesi ‘Equals’ fonksiyonu neticesinde ‘true’ değerini döndürmekteydi. Benzer mantık record struct’lar için de geçerlidir. Aynı değerlere sahip iki record struct verisi karşılaştırıldığında her zaman ‘true’ sonucunu döndürecektir.

  • Printing Members
    record struct’ların getirdiği son yenilik ise elemanlarını direkt olarak string türüne ‘ToString’ fonksiyonuyla çevirdiğimizde bizlere verinin metinsel halini sunmasıdır. Bu durumu aşağıdaki görsel üzerinden daha net değerlendirebiliriz.
    C# 10 - Record StructsDikkat ederseniz esasında bu özellik record class’lar da mevcutken normal struct’lar da değildir.
  • Primary Constructor
    record struct’lar, tıpkı record class’lar da olduğu gibi positional records kullanılıyorsa normal constructor tanımlanmasına izin vermemektedir.

    • Hatasız : C# 10 - Record Structs
    • Hatalı : C# 10 - Record Structs
    • Hatalı : C# 10 - Record Structs
    • Hatalı : C# 10 - Record Structs

Mikro seviyede yapılan optimizasyonlar neticesinde record struct’ların, normal struct’lara oranla 20 kat daha performanslı olduğu gözlemlenmiştir.

Nihai olarak,
Normal şartlarda struct veri türleri class’lara nazaran performans açısından oldukça avantajlıdırlar. record’lar ise struct’lara nazaran class’lara karşı kısmı bir avantaja sahiptirler. C# 10 ile gelen bu record struct’lar ise performansta struct’ları da sollamış bulunuyorlar. Kritik noktalarda kullanmanın koda, performansa ve maliyeti düşürmeye inanılmaz faydası olacağı kanaatindeyim.

İ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.