Record C# 9.0 ile hayatımıza katılmıştır. Herhangi bir nesnenin propertylerine ilk değerlerinin verilmesi ve sonraki süreçte bu değerlerinin değiştirilmemesini garanti altına almamızı sağlayan Init-Only Properties özelliği gelmiştir. Bu özellik sayesinde nesnenin sadece ilk yaratılış anında propertylerine değer atanmakta ve böylece iş kuralları gereği runtime’da değeri değişmemesi gereken nesneler için ideal bir önlem alınmaktadır.
Init-Only Properties
Init-Only properties, developer açısından süreç esnasında değiştirilmemesi gereken property değerlerinin -yanlışlıkla- değiştirilmesinin önüne geçmekte ve böylece olası hata ve bug’lardan yazılımı arındırmaktadır.
Record’larda propertlerin değerini ya tanımlandığı yerde verebiliriz yada contructor içerisinde verebiliriz. Init-only properties özelliğine ‘init’ keyword’ü eşlik etmektedir.
Class MyClass(){
public string Name {get; init; } = "ders10";
public string Author {get; init; }
public Book()
{
Author = "10 ders";
}
}
Yukarıdaki örnekteki ‘init’ keywordü ile
MyClass myClass = new MyClass()
{
Author = "10 ders";
Name = "ders 10";
}
Object initializer içerisinde propertylere değer ataması yapabiliyoruz.
Böylece C# 9.0 yeniliklerinde olan init-only-property sayesinde, nesnelerin ilk yaratılış esnasında salt okunabilir değerlerini vermek için Object Initializer’ı bloklamadan kullanabilmekteyiz.
Init-only properties olmadan kullanım ise
class MyClass
{
public int MyProperty {get; } = 3;
}
bu şekildedir.
Read only propertylere ‘getter-only-properties’ denir.
Records Nedir?
C# 9.0 ile gelen Init-Only Properties özelliği, nesne üretim esnasının dışında değişmez değerler oluşturulması için contructor ve auto property initializers yapısının yanında object initializer yapısının kullanıabilir olmasını sağlıyordu.
Bir nesnenin içerisindeki tüm propertler readonly olamayacaksa readonly olacak olan propertler Init-Only peroperty ile ayarlanabilir fakat bir nesnenin içerisindeki tüm propertyler read only olacaksa Init’den daha fazlasına ihtiyacımız olacaktır. Burada da Records’ın varlığına ihtiyaç duyarız.

Record, bir objenin topyekün olarak sabit/değişmez olarak kalmasını sağlamakta ve bu durumu güvence altına almaktadır. Böylece bu obje, artık değeri değişmeyeceğinden dolayı esasında objeden ziyade bir değer gözüyle bakılan bir yapıya dönüşmektedir.
Nesne ön plandaysa bu class, nesnenin değerleri ön plandaysa bu record’dur
Buradan yole çıkarak rocord’ları, içerisinde data barındıran lightweight(hafif) class’lar olarak değerlendirebiliriz.
Record’lar, class’lara istinaden objeden ziyade içerisinde bulunan dataları sabitleyerek, nesneden ziyade verilerini/datalarını öne çıkartmaktadır.
Record’lar bir class’tır. Sadece nesnelerinden ziyade, değerlerini ön plana çıkmış bir class.
Örnek olarak; Benim şahsım ile ilgileniyorsa yani bir bütün olan benle ilgileniyorsa buna class denir. Fakat benden, benim oluşturduğum bir bütünden ziyade gözlerimin rengiyle, boyumla, yaşımla v.b şekilde belli bir özelliğim yahut özelliklerim hakkında ilgileniliyorsa buna record deriz.

Her iki türde de veriler objede tutulmakta lakin record’lar class’lara nazaran, bir objeden ziyade topyekün veri imajında olacak şekilde spesifik bir davranış sergilemektedirler.
Record Tanımlama
record MyRecord{
}
şeklindedir.
record MyRecord
{
public int MyProperty {get; set;}
}
class MyClass
{
public int MyProperty {get; set;}
}
MyClass m1 = new MyClass()
{
MyPropert = 5
}
MyClass m2 = new MyClass()
{
MyProperty = 5
}
Console.WriteLine(m1.Equals(m2)); //false dönecektir.
MyRecord m3 = new MyRecord()
{
MyProperty = 5
};
MyRecord m4 = new MyRecord()
{
MyProperty = 5
};
Console.WriteLİne(m3.Equals(m4)); //true dönecektir.
Biz buradaki yapılanmaları iki farklı nesne olarak görüyoruz fkat compiler seviyesinde bunlar evet iki farklı nesne ama record oldukları için değerleri ön plana çıkıyor ve bu iki farklı nesnenin içlerindeki propertlerin aynı değerlere sahip oldukları sürece iki aynı değermiş muamelesi görüyor.
Bu şekilde tanımlanan record’lara ise Norminal Records(Normal Kayıtlar) denmektedir.
public record Book
{
public string Name {get; init;}
public string Author {get; init;}
}
Record kullanırsak değiştirilemez propertyler oluşturmak zorunda değiliz.
With Expressions
Immutable türlerde çalışırken nesne üzerinde değişiklik yapabilmek için ilgili nesneyi ya çoğaltmamız/klonlamamız(deep copy) ve üzerinde değişiklik yapmamız gerekmekte ya da manuel yeni bir nesne üretip mevcut nesnedeki değerleri, değişikliği yansıtacak şekilde aktarmamız gerekmektedir.
Eskiden yazılımcıların deneyiminden meydana çıkan With() metodu oluşturulurdu.
public int MyProp1 {get; init;}
public int MyProp2 {get; init;}
public MyClass With(int property2)
{
return new MyClass
{
MyProp1 = this.MyProp1,
MyProp2 = property2
};
}
//şeklinde tanımlanıp
MyClass m = new MyClass{
MyProp1 = 5,
MyProp2 = 10
};
MyClass m2 = m.With(15);
// şeklinde kullanılır.
Bu işlem daha kötü bir yolla aşağıdaki şekildeki gibi de kullanılabilir
MyClass m = new MyClass{
MyProp1 = 5,
MyProp2 = 10
};
MyClass m2 = new MyClass
{
MyProp1 = m.Property1;
MyProp2 = 15;
}
Ancak bunlara gerek kalmadan with expression ile kolaylıkla kullanılabilir.
public record Employee
{
public string Name {get; init;}
public string Surname {get; init;}
public string Position {get; init;}
}
Employee employee1 = new Employee
{
Name = "John",
Surname = "Doe",
Position = 1
};
Employee employe2 = employee1 with {Position = 2};
Employee employe3 = employee1 with {Name = "John Doe"};
Employee employe4 = employee2 with {Name = "JohnDoe", Position = 1};