Why Do We Need Properties?

عرفنا قبل كده إن أي حاجة بنعرفها كـ private مبقدرش أوصلها غير جوه الـ class اللي أنا فيه بس. بس في بعض الأحيان، ببقى محتاج أوصل للمتغيرات دي من بره الـ class. هنا بيجي دور الـ properties.

الـ property تعتبر مزيج (Combination) بين الـ variable والـ method. هي في الأساس بتحتوي على اتنين methods داخليين:

  • الـ get method: عشان تقرا القيمة.
  • الـ set method: عشان تكتب أو تعدل القيمة.

الـ properties حلتلنا مشكلتين أساسيتين:

  1. حافظت على مبدأ الـ Encapsulation وحماية البيانات.
  2. خلت طريقة الاستخدام سهلة جدًا، اكنك بتستخدم public variable عادي خالص بنفس شكل الكتابة بدون تعقيد الـ methods.

Full Property Example

خلينا نشوف مثال عملي على الـ Full Property:

class Person
{
    // Private field
    private string name; 
    
    // Public property
    public string Name 
    {
        get { return name; } // get method
        
        set { name = value; } // set method
        
        // Example of validation with internal modifier:
        // internal set { name = value.Length > 20 ? value : value.Substring(0, 20); }
    }
}
 
class Program
{
    static void Main()
    {
        Person myObj = new Person();
        
        // Used property like a normal variable
        myObj.Name = "Corn"; 
        
        Console.WriteLine(myObj.Name); // Output: Corn
    }
}

زي ما إنت شايف، طريقة الاستخدام بره الـ class بتكون كأنك بتتعامل مع متغير عادي جدًا.

الـ Best Practice: من أفضل الممارسات في كتابة الكود إنك تستخدم نفس الاسم للـ property والـ private field بتاعها، بس بتخلي أول حرف في الـ field صغير (lowercase) وأول حرف في الـ property كبير (Uppercase أو PascalCase).


Automatic Properties (Short Hand)

اللي شرحناه فوق ده اسمه Full Property. بس أحيانًا إنت مش بتبقى محتاج تكتب كل ده لو معندكش Validation (شروط معينة) على الداتا. هنا تقدر تستخدم حاجة اسمها Automatic Properties.

في الـ Automatic Properties، إنت مش محتاج تعرّف الـ field بنفسك، كل اللي عليك تعمله إنك تكتب get; و set; جوه الـ property وخلاص.

class Person
{
    // Automatic property
    public string Name { get; set; }
}

طيب الداتا دي بتتخزن فين لو مفيش private field؟ الـ Compiler هنا ذكي، هو اللي بيكريت backing field (يعني Hidden Private Attribute) من ورا الكواليس عشان يخزن فيه القيمة.

لو استخدمنا أداة زي ILSpy (وهي أداة بتعمل Decompile للكود عشان تشوف أصله)، هنلاقي إن الـ Compiler عمل Attribute Private للـ Property دي من غير حتى ما إحنا نكتبه بإيدينا.

graph LR
    A["Auto Property <br> public string Name { get; set; }"] -->|Compiler generates| B[Hidden Private Backing Field <br> e.g., &lt;Name&gt;k__BackingField]
    A -->|Compiler generates| C[get_Name method]
    A -->|Compiler generates| D[set_Name method]

Notes About Properties

فيه شوية ملاحظات مهمة جدًا لازم تكون عارفها وإنت بتتعامل مع الـ properties:

  • الـ property ما هي إلا method: من ورا الكواليس، هي بتتحول لـ methods. فتقدر تطبق عليها حاجات كتير من خصائص الـ methods زي إنك تعملها override، بس الفرق الأساسي بيكون في طريقة الكتابة السهلة.
  • جوه الـ property: بتستخدم الـ private attribute (اللي بيكون اسمه بحرف small) عشان تقرا منه أو تكتب فيه.
  • جوه الـ methods اللي في نفس الـ class: يُفضل إنك تستخدم الـ private attribute مباشرة عشان ميعملش overhead (حِمل زيادة على الذاكرة أو الأداء). لكن، لو الـ property بتاعتك فيها filtration أو validation (شروط معينة بتتنقل الداتا من خلالها)، يبقى الأفضل تستخدم الـ property جوه الـ class عشان متضطرش تعيد كود الـ validation تاني.
  • بره الـ class: بنستخدم الـ property دائمًا (اللي بتبدأ بحرف Capital).
  • الـ single input parameter: الـ property بتشتغل على مدخل واحد بس (اللي هو الكلمة المحجوزة value). وعشان كده مقدرش أعمل للـ property حاجة اسمها Overloading زي ما بنعمل مع الـ methods.
  • التحكم في القراءة والكتابة: أقدر أخلي الـ Property تبقى Read-only (للقراءة فقط) من خلال إني أشيل جزء الـ set منها. أو العكس، أخليها Write-only لو شلت الـ get.

Code Snippets

عشان تسرّع كتابتك للكود في بيئة التطوير (زي Visual Studio)، فيه Code Snippets جاهزة بتوفر عليك وقت:

  • الـ Full Property: بتكتب كلمة propfull وبعدين تدوس على زرار Tab مرتين. ده هيكريتلك الـ private field بالـ public Property بتاعته فورًا.
  • الـ Automatic Property: بتكتب كلمة prop وبعدين تدوس Tab مرتين، وهيعملك سطر الـ get; set; القصير.

Note

  • موضوع الـ Overloading: مينفعش يتعملها Overloading لإنها بتُعرّف باسمها فقط (مفيش Signature فيه Parameters زي الـ Methods). الاستثناء الوحيد للقاعدة دي هو الـ Indexers (اللي هي تعتبر Parameterized Properties)، دي الوحيدة اللي نقدر نعملها Overloading لإنها بتاخد Parameters بين قوسين مربعة `