الحقل والخاصية في C#: خرافات، واقع، والبايت كود
\n\nإذا كنت قد تساءلت يومًا "What is the difference between a field and a property?" في C#، فأنت لست وحدك. هذا أحد أكثر الأسئلة شيوعًا على Stack Overflow بآلاف المشاهدات. بالنسبة للمبتدئين، يبدو الفرق ضبابيًا: كلاهما يخزن البيانات. لكن تحت الغطاء، هما آليتان مختلفتان تمامًا. دعنا نفهم مرة واحدة وإلى الأبد لماذا الخاصية (property) ليست مجرد "حقل مع getter"، بل أداة قوية للتغليف (Encapsulation) وإنشاء العقود (Contracts).
\n\nهذه المقالة ليست توثيقًا جافًا. إنها تحليل حي مع أمثلة يمكنك تشغيلها الآن. استعد، سيكون الأمر ممتعًا.
\n\n\n\n
ما هو الحقل (field) في C#؟
\n\nالحقل هو متغير يُصرَّح به مباشرة داخل الفئة (class) أو الهيكل (struct). يخزن البيانات وليس له أي منطق إضافي عند القراءة أو الكتابة. الحقل هو مخزن "خام".
\n\npublic class Person\n{\n public string Name; // هذا حقل\n}\n\nالأمر بسيط. لكن هناك فارق بسيط: إذا كان الحقل عامًا (public)، فإنك تفقد السيطرة على كيفية الوصول إليه. يمكن لأي كود خارجي كتابة أي شيء فيه، ولن تتمكن من الرد على ذلك (مثل التحقق من طول السلسلة النصية أو استدعاء حدث).
\n\nمشاكل الحقول العامة
\n- \n
- لا يوجد تحكم في التحقق من الصحة (Validation). \n
- لا يمكن تغيير السلوك عند القراءة/الكتابة دون تغيير واجهة API للفئة. \n
- صعوبة الحفاظ على التوافق العكسي (Backward Compatibility). \n
لهذا السبب، في البرمجة الشيئية السليمة (OOP)، الحقول العامة تكاد تكون نمطًا معاكسًا (Anti-pattern). في C#، تم اختراع الخصائص (Properties) لهذا الغرض.
\n\n\n\n
ما هي الخاصية (property) في C#؟
\n\nالخاصية هي عضو في الفئة يبدو كحقل، لكنه في الواقع زوج من الدوال (الملحقات): get و set. هذا هو الجواب الرئيسي على سؤال "What is the difference between a field and a property?". الخاصية هي سكر نحوي (Syntactic Sugar) تختبئ خلفه دوال عادية.
public class Person\n{\n private string _name; // حقل خاص (Private) - حقل داعم (Backing Field)\n\n public string Name // خاصية\n {\n get { return _name; }\n set { _name = value; }\n }\n}\n\nعندما تكتب person.Name = "Alice"، يقوم مترجم C# بتحويل ذلك إلى استدعاء الدالة set_Name("Alice"). وعند القراءة، يتم استدعاء get_Name(). أنت لا ترى ذلك، لكنه يحدث على مستوى كود IL (اللغة الوسيطة لـ .NET).
الخصائص التلقائية (Auto-implemented properties)
\nلتبسيط الأمور، في C# 3.0 ظهرت الخصائص التلقائية. يقوم المترجم بإنشاء حقل داعم خاص بنفسه. يصبح الكود أقصر، والوظيفة هي نفسها.
\n\npublic class Person\n{\n public string Name { get; set; } // خاصية تلقائية\n}\n\nعلى مستوى IL، لا يزال هذا يتحول إلى دالتي get_Name و set_Name مع حقل خاص. لا يوجد سحر - مجرد راحة.
\n\n
الاختلافات الرئيسية بين الحقل والخاصية: جدول
\n\nلترسيخ المعلومة، إليك مقارنة توضيحية. سيساعدك هذا في الإجابة بسرعة على سؤال "field vs property C#" في مقابلة عمل أو في مشروع حقيقي.
\n\n- \n
- التغليف (Encapsulation): الحقل - مجرد متغير. الخاصية - دوال وصول يمكن أن تحتوي على منطق. \n
- التحقق من الصحة (Validation): في الخاصية، يمكن إضافة فحص في الـ setter. في الحقل - لا. \n
- الإشعارات (Notifications): في الخاصية، من السهل استدعاء حدث (مثل INotifyPropertyChanged). في الحقل - ستحتاج إلى إعادة هيكلة (Refactoring). \n
- الافتراضية (Virtual): يمكن أن تكون الخصائص افتراضية (Virtual)، مجردة (Abstract)، وقابلة للتجاوز (Override). الحقول - لا. \n
- العمل مع الخيوط (Threading): في الخاصية، يمكن إضافة قفل (lock). في الحقل - فقط من خلال وسائل خارجية. \n
- التسلسل (Serialization): غالبًا ما تعمل أدوات التسلسل مع الخصائص وليس الحقول (خاصة إذا كا