Record In C# Deep Dive - Part 1

ال Record نزل مع ال C#9 / Dotnet 5  ومهم هنا تبقى عارف الـ Features المهمة نزلت امتى عشان لو نقلت من Project للتانى أو من شركه للتانية تبقى عارف ايه الادوات اللى معاك وازاى  تقدر تستخدمها
Record In C# Deep Dive - Part 1

في هذه الصفحة

ايه المميزات اللى ممكن تحصل عليها بسطر واحد فقط من الـ Code Snippet ده ؟! 

record Employee(string FirstName, string LastName, double Salary);

الإجابة هتلاقيها بنفسك لما تبص في الـ Code Snippet الجاي : 

public class Employee
{

    // properties
    public string FirstName { get; }
    public string LirstName { get; }
    public double Salary { get; }


    // constructor
    public Employee(string firstName, string lastName, double salary)
    {
        FirstName = firstName;
        LastName = lastName;
        Salary = salary;
    }

    // optional: you can override toString() for better representation
    public override string toString()
    {
        return $"Employee {FirstName} {LastName}, Salary: {Salary}";
    }

    // optional: you can override Equals() and GetHashCode() for value comparison
    public override bool Equals(object obj)
    {
        if(obj is Employee otherEmployee)
        {
            return FirstName == otherEmployee.FirstName &&
            LastName == otherEmployee.LastName &&
            Salary == otherEmployee.Salary;
        }
        return false;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(FirstName, LastName, Salary);
    }

}

تخيل كل الـ Class اللى فى الـ Code Snippet التاني بكل الـ Features اللى فيه زى : 

  • الـ Immutability 
  • الـ Comparison base on values
  • الـ Print ‘ToString’ 

بالإضافة لمميزات تانية لسه هنتكلم عليها، انت قدرت تحصل عليها بسطر واحد فقط من الـ Code عن طريق استخدام Record

يلا نبدا ونشوف الكلام ده بيحصل ازاى و نتعرف أكتر على الـ  Record و بعد المقال ده هتفهمه كويس وهتقدر تطبقه و تستفيد منه فى شغلك بشكل جميل.

بداية الـ Record

أولا ال Record نزل مع ال C#9 / Dotnet 5  ومهم هنا تبقى عارف الـ Features المهمة نزلت امتى عشان لو نقلت من Project للتانى أو من شركه للتانية تبقى عارف ايه الادوات اللى معاك وازاى  تقدر تستخدمها، و مهم طبعا تبقى مطلع على كل ما هو جديد عشان تستفيد من التحسينات اللى بتنزل كل فترة والـ Code بتاعك يبقى أحسن و ميبقاش Legacy بمرور السنين

طيب ايه هو ال Record وايه مميزاته؟

طبقا للتعريف اللى على موقع Microsoft 

“A record in C# is a class or struct that provides special syntax and behavior for working with data models. The record modifier instructs the compiler to synthesize members that are useful for types whose primary role is storing data”

فهو نوع معين من الـ Class / Struct
” اللى هما فى الأخر عبارة عن “Container”  بيقدر يشيل جواه Data أو Behavior أو الاتنين مع بعض “لكن ليه خصائص مختلفة و مميزة عن الأنواع دى و عن طريق استخدام الـ Record Modifier فقط هتقدر تستفيد بكل الخصائص و هتساعدك تتعامل مع الـ Data بشكل أسهل زى ما شوفنا فى أول مثال. 

فبطريقة مختصرة جداً ال Record  هو عبارة عن طريقة مبسطة للتعامل مع الـ Data   

تعالوا نبدأ بالـ Record اللى موجود فى C#9 / Dotnet 5 “ ونتكلم عنه هنا فى جزء لوحده عشان لو حد لسه شغال بالـ  Version دى يعرف ايه هي المميزات اللي هياخدها من الـ Record  وايه المميزات الاضافية لما يطلع لـ Version أعلى ، وبالمناسبة مفيش تغييرات حصلت بل فيه اضافات فأنت حتى لو شغال ب Version أعلى فهتكون محتاج الجزء ده عشان نبني عليه.

لحد الـ Version  دى كان Record عبارة عن Reference Type  فقط ويستخدم كبديل للـ Classes  لنقل الـ Data بالاضافة لبعض المميزات التانية:

1- Immutability 

أول حاجة وأهم حاجه هى الـ Immutability وهى ببساطة انك متقدرش تعدل فى الـ Data اللى شايلها الـ Object أو كما يطلق عليها Object State  بعد ما يحصله Create / Initialization  و دى حاجه مهمة جدا بتحميك من مشاكل كتير خاصة لو الـ Object  بتاعك بيروح من مكان لمكان فبتضمن ان محدش هيغير فيه فى الطريق من غير ما انت تاخد بالك وبالتالى هيقلل المشاكل الغير متوقعة، وعشان كده هتلاقى مستخدمة فى فيديوهات و مقالات أكتر الوقت كـ DTO  أو Data Transfer Object  وهى Types بتستخدم لنقل البيانات من مكان للتانىتعالوا نشوف ال Immutability فى المثال الجاى ده

Immutability
Immutability

هتلاقى هنا علطول حصل Compiler Error بيوقفك و يقولك انك متقدرش تعدل فى ال Property وانك تقدر بس تحط  Value ليها اثناء الـ Initialization

2- Comparison Based on Values

مقارنة الـ Reference Types  بناءا على ال Values مش على الـ Reference  و ده لم يكن موجود ابدًا فى الـ Class وكنت بتحتاج تكتبلها Custom Code زى ما شوفنا فى ال  Class الموجودة فى أول المقال .. لكن باستخدام ال Record تقدر فقط تعمل الاتى: 

var employee1 = new Employee("Mohamed", "Magdi", 1000);
var employee2 = new Employee("Mohamed", "Magdi", 1000);
var employee3 = new Employee("Ammar", "Ali", 2000);

Console.WriteLine($"Is Equal = {employee1} {employee2}"); // Output: IsEqual = True
Console.WriteLine($"Is Equal = {employee1} {employee3}"); // Output: IsEqual = False

record Employee(string FirstName, string LastName, double Salary);

طبعا عشان نحقق نفس الكلام باستخدام الـ Class العاديه كنا هنروح نـ Override ال Equals Method عشان نغير ال Behavior بتاعها زى ما شوفنا فى المثال اللى فى أول المقال

3- Concise Way to Define a Reference Type with Immutable Properties 

طريقة مختصرة جدا عشان تعرف Reference Type ب Immutable Typesوعشان كنا نعمل كده باستخدام الـ Class كنا هنكتب أكثر وأصعب و طبعا كل ما كان الكود مختصر هيبقى أسهل في القراءة والصيانة

record Employee(string FirstName, string LastName, double Salary);

4- Built-in Copy Constructor

ميزة كمان مهمة وهي انك تعمل Object  جديد باستخدام Object قديم و تنسخ نفس البيانات اللي فيه وتقدر برده تغير اللى انت عايزه

public record Person(string FirstName, string LastName);

public static void main()
{
    Person person1 = new("Mohamed", "Magdi");
    Console.WriteLine(person1);
    // output: Person {FirstName = Mohamed, LastName = Magdi}

    Person person2 = person1 with { FirstName = "Mahmoud" };
    Console.WriteLine(person1 == person2); // output: False

    Person person3 = person1;
    Console.WriteLine(person3);
    // output: Person {FirstName = Mohamed, LastName = Magdi}
}

5- Built-in Formatting for Display

وهنا من غير ما تكتب أي Code لو جيت تطبع ال Object  بتاعك كـ Text عن طريق الـ ToString() Default Implementation  زى المثال الجاى:

var employee1 = new Employee("Mohamed", "Magdi", 100);

Console.WriteLine(employee1); // Output: Employee { FirstName = Mohamed, LastName = Magdi, Salary = 1000}
record Employee(string FirstName, string LastName, double Salary);

6- Support for Inheritance Hierarchies

وهنا المقصود انك تقدر تـ Extend  الـ Record  زى ما بتعمل مع ال Class  زى المثال اللى جاى

public abstract record Person(string FirstName, string LastName);

public record Teacher(string FirstName, string LastName, int Grade) : Person(FirstName, LastName);
public record Student(string FirstName, string LastName, int Grade) : Person(FirstName, LastName);

public static void main()
{
    Person teacher = new Teacher("Mohamed", "Magdi", 3);
    Person student = new Student("Mohamed", "Magdi", 3);

    Console.WriteLine(teacher == student); // output: False

    Student student2 = new Student("Mohamed", "Magdi", 3);
    Console.WriteLine(student2 == student); // output: True
}

هنا ال Output  الأول قيمته بـ False عشان هو بيقارن Type  و Values  مش Values  بس

طيب الـ Record ده طلع كويس، امتى استخدمه؟ 

1- Simple Data Transfer Objects (DTO) 
اللى بتستخدم فى نقل البيانات من Layer  للتانية

2- Lightweight Types without Behavior
أنواع خفيفة مش محتاج منها  Behavior محتاج بس انها تشيل Data

3- Immutable Data Models
لو عايز ابنى Data Models محدش يقدر يغير فى ال State بتاعتها

4- Improve Safety and Containment
تغيير الـ State  لما بيكون بس من خلال الـ Constructor  بيخلى ال Behavior  متوقع أكتر

5- Avoid Bugs from Unexpected State Mutation
مشاكل كتير بتحصل من التغيير غير المتوقع للـ  State من أى مكان و باستخدام الـ  Records هتقدر تمنع المشاكل دى عن طريق ال Immutability

طيب امتى مستخدموش؟ 

  1. لو عايز مستوى أعلى من التحكم فى خصائص الـ Container بتاعك، احنا شوفنا ان الـ Records بيديك شوية Functionalities جاهزة و الحاجات دى مش هتقدر تتحكم فيها أو تغيرها بعكس الـ Class  مثلا تقدر تتحكم أكتر و تغير الـ Behavior  بتاع الـ Equals و ال toString  وشوية حاجات تانية كمان
  2. لو عايز تستفيد بخصائص كتير من الـ Inheritance  و Polymorphism  هنا الـ Record  مش هيبقى Flexible  معاك بشكل كافى و برده الـ Class هتكون خيار أفضل
  3. لو عايز تسمح بالـ Immutability  و ماعندكش مشكله فى تغيير الـ State  الخاصة بالـ Object وقتها الـ Class  هيكون الخيار الأفضل

وبكده  يخلص الجزء الأول اللى اتكلمنا فيه عن الـ Records وايه هى  مميزاتها و امتى استخدمها و امتى مستخدمهاشاتكلمنا على الـ Record Reference Type  و ده الجزء اللى نزل مع DotNet 5  C#9 / و حاولنا نخلى الموضوع بسيط عشان الناس تقدر تطبق و تستفيد فورا بعد ما تخلص الجزء ده.

و الجزء اللى جاى ان شاء الله هنتكلم عن الاضافات اللى نزلت فى ال C#10/Dotnet 6 و ازاى بدأ يدعم ال Value Type  كمان عن طريق Struct Record  و هنشوف كمان حاجات  Advanced عن الـ Record  حالات استخدام تانيه و طرق تانيه لكتابته و تأثيره على الكود. 

المصادر: 

Records in C# - C#
Learn about C# record types and how to create them. A record is a class that provides value semantics.

اشترك الآن بنشرة اقرأ-تِك الإخبارية

لا تدع أي شيء يفوتك. واحصل على أحدث المقالات المميزة مباشرة إلى بريدك الإلكتروني وبشكل مجاني!
رائع! تحقق من بريدك الإلكتروني واضغط على الرابط لإكمال تسجيل الدخول.
حدث خطأ! من فضلك قم بادخال بريد إلكتروني صحيح!