.NET 8 İLE GELEN YENİLİKLER VOL 2.0

Selamlar,

Bu makale, .Net 8.0 ile gelen yenilikler makalesinin devamıdır.

Streaming Deserialization: Otomatik Tanımlanan Sınıfa Deserialization

Amaç bir servisten kayıt çekilirken, çekilen datanın ayrıca bir deserialize işlemine tabi tutulmadan otomatik olarak ilgili modele maplenmesidir.

Örnek amaçlı kayıt çekilecek 3th party servis: https://microsoftedge.github.io/Demos/json-dummy-data/64KB.json

İlgili C# modeli Json model, burdan oluşturulur: https://json2csharp.com

CodPlayer servisden dönen modeldir. ShortCodPlayer bizim esas ihtiyacımız olan ve geri döndüğümüz modeldir.

GetAllCodPlayers(): Tüm kaydın çekildiği ve otomatik olarak CodPlayers’a maplendiği methoddur.

Aşağıda görüldüğü gibi “GetFromJsonAsAsyncEnumerable<CodPlayers>()” ile otomatik “CodPlayers”‘a gelen Json data, CodPlayers’a maplenmektedir. Geriye

IAsyncEnumerable<CodePlayers?>” tipinde değer dönmektedir.

Aşağıda görüldüğü gibi “players” üzerinden stream olarak kayıt gelmeye devam etmektedir. “await” keyword’ünü artık foreach başında .NET 8.0 ile kullanabilmekte ve anlık akan datayı geri dönülecek esas “shortPlayList“‘e  ataya bilmekteyiz. Çünkü ihtiyacımız olan sadece servisten dönen 2 kolondur. “name“ve “version“. Yani aslında “players“‘a tüm data çekilerek döngüye girilmemiş, sürekli asenkron gelen data players’a dolmakta, biz de her gelen datayı shortPlayerListe eklemekteyiz.

Son olarak gelen liste, “versiyon”‘a göre aşağıda görüldüğü gibi sıralanmaktadır.

GetAllCodPlayers():

Result: Sonuçların bir kısmı aşağıda görüldüğü gibidir.

AsyncEnumerableExtensions:

  • Peki, çekilen IAsyncEnumerable data üzerinde Linq sorgusu yazmak istersek öncelikle aşağıdaki Extension sınıfını yazmamız gerekmektedir. Çünkü IAsyncEnumerable LINQ Query desteklememektedir. İhtiyaçlara göre “SelectAsync()“, “WhereAsync()“, “OrderByAsync()” ve “ToListAsync()” extension methodları yazılmıştır.
  • Bu methodlarda “yield” keyword’ü ile asenkron şekilde gelen data, streaming olarak anlık geri dönülmektedir.
  • Özellikle büyük datalarda hepsinin toplu çekilip geri dönülmesi, hem performans hem de zaman kaybına neden olmaktadır. Ayrıca bir Linq Library’de giren datanın tipinin değişmemesi gerekmektedir. Örneğin “SelectAsync()“‘den sonra data tipi değişir ise, ondan sonra eklenen “ToListAsync()” extension’i çalışmayacaktır.
  • Bu anlık streaming yapısını “OrderByAsync()” extension’i, aslında bozmktadır. Ama her zaman ihtiyaç duyulabilecek bir method olduğu için, kütüphaneye eklenmiştir. Sorun: Çekilecek olan datanın, sıralamanın yapılabilmesi için tamamının beklenmesi ve anlık streaming işinin durdurulmasıdır. Ancak tüm data çekildikten sonra, bir sıralama işlemi yapılabilmektedir.

AsyncEnumerableExtensions.cs: 

Şimdi gelin kodlarımızı, yukarıdaki Extension methodlara göre tekrardan elden geçirelim.

GetAllCodPlayers():

  • Aşağıda görüldüğü gibi öncelikle “GetFromJsonAsAsyncEnumerable()” methodu ile 3. bir endpoint’den datalar çekilmiş ve “CodPlayers” modeline otomatik Deserialize edilmiştir.
  •  :Çekilen CodPlayers datası, “language” kolonu “Sindhi” olanlar ile filitrelenmiştir.
  • :Filitrelenen datalar içinden, bizim ihtiyacımız olan sadece “name” ve “version” alanları alınmıştır. Böylece ayrıca bir ShortCodPlayer modeline ihtiyaç duyulmamıştır.
  • : Son olarak versiyon propertysine göre sıralama yapılmıştır. Bu sırada maalesef tüm datanın çekilmesi beklenmiştir. Bu nedenle anlık streaming özelliğine son verilmiştir. Sonda tüm data, Task<List<T>>? ‘e dönüştürülmüştür.
  • :”await shortPlayerList” ile tüm data List<T>() olarak result’a atanmıştır. Böylece “GetEnumerator()” call edilebilmiş ve foreach içerisinde sonuçlar ekrana basılmıştır.

Result:

FrozenSet, FrozenDictionary :

İlk oluşturma süresi zahmetli olsa da, okuma hızlarında gözle görülebilir bir performans farkı bulunmaktadır. Bu listelere eklenen elemanlar Immutable‘dır.

Aşağıda örnek FrozenList ve FrozenDictionary kullanımı görülmektedir.

Benchmark Test: Aşağıdaki benchmark testine bakıldığında, “CreateFrozenList()” diğer List ve HashSet’e göre çok daha uzun bir sürede yaratılmıştır. Ama örnek FrozenDictionary içinde => TryGetValue() ile ilgili kayıdın çekilmesi diğer List ve HasSet’e göre çok daha performanslıdır.

Burdan çıkarılacak sonuç, eğer yaratılma zamanı mesela en başta yaratılması çok dert değil ise,  data okunma veya çekilme anında, özellikle büyük data kümelerinde bize büyük bir performans kazandıracaktır.

global Using:

Hepinizin bildiği “alias” namespace’e takma isim kullanımı, .Net Framework’un 1.0 versiyonundan beri vardır. Aşağıdaki örnekte alias tip kullanımına bir örnek verilmiştir. İşte global Using ise bunun Custom Tip tanımlama versiyonudur.

Aşağıdaki örnekte ShoppingData tipi, Global olarak tüm projede kullanılabilecek şekilde tanımlanmıştır. Böylece ShoppingDate tipi ile, ServiceType ve Basket tipleri ayrı ayrı tanımlanma yerine tek bir tip altında toplanmaktadır.

Örnek Kullanım Şekli: Aşağıda görüldüğü gibi data, “ShoppingData” tipinde yaratılmıştır. Ve bu ShoppingDatat tipi, başka hiçbir yerde tanımlamaya gerek kalmadan, tek bir yerde yazılıp, Global olarak kullanılmıştır.

    • İlgili product 3th party servisten çekilerek, otomatik olarak ResultModel’e maplenmiştir.
    • Çekilen productlar, otomatik artan id değerleri ile FozenDictionary’e cast edilip dicktProduct değişkenine atanmıştır..
    • Global Type olarak tanımlı “ShoppingData” tipindeki data’ya yukarıda tanımlanan “dicktProduct” ve ServiceType Enum’undan “weather”  propertyleri ile tanımlanmıştır.

Product ve ResultModel Sınıfları ve ServiceType Enum: 

 

Switch Expression:

Aşağıda görüldüğü gibi .NET 8.0 ile bir string dizi içerisinde GroupBy Linq Query yazarken, switch tanımlaması yapılabilmektedir.

Aşağıdaki string [ ] içinde tanımlı kelimeler boyutlarına göre guruplanmış, 5’den küçük, 5 ile 8 arası ve diğerleri koşullarına göre “Name” property’si atanmış, “Id” propertysi de sıralı olarak arttırılarak atanmıştır. Select işleminin sonunda da groupResult değişkenine, ilgili result “FrozenSet()”‘e dönüştürülerek atanmıştır.

Result:

ref readonly: 

Amaç, referans ile verilen değişkenlerin sadece kullanılmasını ama asla değiştirilememesini sağlamaktır.

Aşağıdaki örnekte ref readonly olarak tanımlanmış id değerini değiştirilememektedir. Mesela id=5 şeklinde bir atama yapılamaz. Hatta “id.ToString()” şeklinde cast bile yapılamayacağı  için, başka bir num değişkenine atanmış ve o değişken ToString() olarak RedisKey’e string bir parametre olarak atanmıştır.

Int ToString() Performans Geliştirmesi

Son olarak .NET 7.0 => .NET 8.0’a geçişte “Int ToString()” için muazzam bir performans artışı sağlanmıştır. Aşağıda bununla ilgili BenchMark test sonucu görülmektedir. Proje içinde bolca kullanılabilecek bu dönüşüm .Net 7.0’dan => .Net 8.0’a geçildiğinde büyük bir performans artışı olarak geri dönecektir.

Geldik bir makalenin daha sonuna. Bu makalede .Net 8.0 ile gelen diğer yeniliklerden bahsettik. Yeni bir makalede görüşmek üzere hepinize hoşçakalın.

 

Herkes Görsün:

Bunlar da hoşunuza gidebilir...

Bir cevap yazın

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