C# 10 Record Struct

Selamlar,

Museum of Pop Culture in Seattle, WA designed by Frank Gehry.

C# 9.0 ile hayatımıza giren recordlar, aynı classlar gibi davranıp aynı zamanda birçok ekstra özelliği barındırmaktadırlar. En önemli özellikleri immutabale, yani “init-only” property’si ile değişmez olmalarıdır. Böylece kullanım alanlarına göre, hata riskini minimum’a indirmektedirler. Recordlar üzerine daha detaylı bilgiye, önceki makalemden ulaşabilirsiniz.

Bugünkü konuşacağımız konu, aşağıda görüldüğü gibi structlar’ın record olarak tanımlanması ile kazandıkları yeni kabiliyetlerdir.

Global dünyada C#’da bolca kullanılan, ama iş hayatında Code Review yaptığım kodlarda nerde ise hiç göremediğim “Structlar”‘ı, isterseniz önce kısaca bir hatırlayalım.

Bilindiği gibi Classlar referance typedır ve “Heap” bellekte saklanırlar. Ama structlar value type ve “Stack” bellekde saklanırlar. Heap bölgesindeki bir nesneye erişmek, ayrıca bir zaman ve fazladan bellek kullanımına neden olacağından, içinde az sayıda eleman içeren ve sadece bir veri tipine sahip değişkenleri sınıflar yerine structlarda tanımlamak, performans ve verimlilik açısından çok daha faydalıdır. Bana göre structların en büyük eksiği Inheritance’ı desteklememesidir. Ve en büyük artısı da Stack bellekde saklandıkları için, GC’a ihtiyaç duyulmamalarıdır. İşleri bitince stack bellekden, usulca silinirler. Bu nedenle de, IDisposable yani Deconstructor() methodlar structlar için yasaklanmıştır.

Aynı classlarda olduğu gibi istenir ise new() anahtar sözcüğü ile Constructor çağırlabilir. Ama classlardan farklı olarak aşağıda görüldüğü gibi new() keyword’ü kullanılmadan da çağrılabilir.

Ya da istenir ise structlar, “new()” keyword ile de aşağıdaki gibi kullanılabilirler. Tek önemli husus, yaratılma anında tüm değişkenlerin atanması gerektiğidir.

Aşağıdaki kullanımda, “People.No” atanmadığı için, uygulama derlenmemektedir.

Structlarda hiç değer atanmasa bile “new()” keyword’ü ile kullanılmaları durumunda, default değerler atanmış olur. Aşağıda görüldüğü gibi bora People struct’ına hiç değer atanmadığı halde “new()” keyword’ü ile tanımlandığı için, ekrana No “0” olarak yazdırılmıştır.

Structlar value type olduklarından dolayı  classların aksine, bir method’a parametre olarak atanıp değiştirildiklerinde, kendileri değişmezler. Aynı durum, classlar için geçerli değildir. Classlar, methodlara parametre olarak Referance tipi olarak atandıkları için, method içi parametre değişiminde  kendileri de değişirler. Aşağıdaki örnekde, kullanım ve ekran çıktısı gözükmektedir.

Kısaca Structlar:

  1. GC’a ihtiyaç duymamaları ve böylece çok daha az sistem tüketmeleri.
  2. Stack’de saklandıkları için, erişimleri ve propertylerinin kopyalanma hızları sınıflara göre çok daha yüksek ve performanslı olmasından dolayı, içinde fazla propertysi olmayan, primitive typeların kullanıldığı, inheritance gerektirmeyen yapılarda örnek ViewModellerde şiddetle tercih edilmelidirler.

Şimdi kısaca Structları hatırladığımıza göre, gelin başlarına “Record” eklediğimiz zaman neler değişiyor hep beraber inceleyelim:

Immutability:

Aşağıda görüldüğü gibi, recordlardan gelen “init” keyword’ü ile tanımlı propertyler, birkere atandıktan sonra değiştirilememktedirler. “Norman.Name“‘in, Constructor’da bir kere atandıktan sonra, tekrardan “Bora” olarak değiştirilmesine izin verilmemektedir.

Recordların” aksine “record structlar“‘da, “positional records”lar farklı davranmaktadır. Aşağıda görüldüğü gibi :

  • Recordlarda” Constructorda tanımlı değişkenler, “init” yani immutable’dır. Kısaca birkere atandıktan sonra, tekrardan değiştirilemezler. Örneğin “Elon” bir record nesnedir. Name, yaratılma anında Constructorda tanımlandığı için, sonrasında Elon.Name=”Bora”‘ya izin verilmemektedir.
  • record struct“‘da durum, biraz farklıdır. Aşağıdaki örnekde Norman record struct bir nesnedir. Constructorda Name,Surname ve No alanı tanımlanmış olmasına rağmen, immutable değillerdir. Ve sonradan da değiştirilebilmektedirler.

Not: “record structların” immutable olması istenir ise, tanımlamada başına readonly koymak yeterlidir.. Örneği aşağıdadır..

With Keyword: 

Aşağıda görüldüğü gibi, “record struct” şeklinde tanımlama ile “with” keyword’ü kullanılarak “shallow copy” işlemi yapılabilmektedir. Yani bora nesnesi, Norman nesnesinin sadece adını değiştirilerek, bir kopyası şeklinde oluşturulmuştur.

İşin ilginç yani, strcutlar da artık “with” keyword’ü ile shallow copy işlemine tabi tutulabilmektedirler. Yani structlar artık “with”‘e destek vermektedir. Kısaca “with” keyword’ü, “record struct“‘a özel değildir.

Structlar artık başlarında record tanımlamaya gerek duymadan “with“‘e destek vermektedir.

Equality eşitlik karşılaştırması:

Aşağıda görüldüğü gibi structlar, “==” veya “!=” eşitliğine destek vermemekte, ve daha kodlama anında aşağıda görülen hatayı vermektedir.

Ama “==” veya “!=” eşitliğine “record struct“lar, aşağıda görüldüğü gibi destek vermektedir.

Print Members:

“record struct”larda, “ToString()” methodu override edilmiştir. Normal “structlar” çıktı olarak bize pek birşey vermez iken, “record structlar” bize struct’ın tüm string halini vermektedir. Aşağıdaki örnekde, “struct” ve “record struct” iki nesne ekrana yazdırılmış ve aradaki fark, bariz bir şekilde görülmüştür.

Record Structlar, bence C# 10 ile gelen ama hak ettiği değeri pek de görmeyeceğini düşündüğüm önemli yeniliklerden sadece biri. Özellikle, kaynaklarda da belirttiğim (nietras.com)’daki Benchmark testleri gösteriyor ki, “record struct”‘lar  => “record”lardan en az x20 kat daha performanslıdır. Tabi bu farkın hissedilebilmesi için, her yerde class tanımlamak yerine, gerçekten gerektiği yerlerde “record struct” lara da bir şansın verilmesi gerekmektedir.

Unutmayın gerçek performans , küçük parçaların verimleri toplamıdır.

Geldik bir makalenin daha sonuna. Yeni bir makalede görüşmek üzere hepinize hoşçakalın.

Source :

Herkes Görsün:

Bunlar da hoşunuza gidebilir...

1 Cevap

  1. samet dedi ki:

    teşekkürler çok güzel bir makaleydi

Bir cevap yazın

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