مقدمة: لماذا حظي سؤال الخصائص التلقائية بآلاف المشاهدات؟
\n\nإذا كنت قد كتبت كودًا بلغة C# من قبل، فبالتأكيد واجهت سؤالًا بسيطًا لكنه مهم: "كيف يتم تعيين القيمة الابتدائية للخاصية التلقائية بشكل صحيح؟". هذا السؤال على Stack Overflow حصد عشرات الآلاف من المشاهدات، وهذا ليس بدون سبب. فالبساطة الظاهرية تخفي العديد من المزالق.
\n\nتخيل: أنت تنشئ كلاس User، وتريد أن تكون الخاصية Name افتراضيًا ليست null، بل سلسلة فارغة. يبدو الأمر بسيطًا، أليس كذلك؟ لكن في الواقع، يقع المطورون في أخطاء نموذجية عند تهيئة خصائص C# تؤدي إلى NullReferenceException أو سلوك غير متوقع.
في هذه المقالة، سنستعرض أهم 5 أخطاء ونوضح كيفية تجنبها. ستتعرف على الأساليب الحديثة - من C# 6 إلى C# 12 - وستفهم أي طريقة تختار لمشروعك.
\n\n\n\n
الخطأ رقم 1: تجاهل تهيئة الخصائص التلقائية
\n\nالخطأ الأكثر شيوعًا هو عدم تعيين قيمة ابتدائية للأنواع المرجعية. كثير من المبتدئين يكتبون:
\n\npublic class User\n{\n public string Name { get; set; } // القيمة الافتراضية null\n public List<string> Roles { get; set; } // null\n}\n\nفي C#، الخصائص التلقائية للأنواع المرجعية تكون قيمتها الافتراضية null. وهذا يؤدي إلى مشاكل NullReferenceException عندما تنسى تعيين قيمة قبل الاستخدام.
كيف تصلح ذلك؟
\nقم دائمًا بتعيين مُهيئ الخاصية التلقائية C# بشكل صريح. أسهل طريقة هي استخدام صياغة C# 6:
\n\npublic class User\n{\n public string Name { get; set; } = string.Empty;\n public List<string> Roles { get; set; } = new List<string>();\n}\n\n\n\n\nنصيحة: استخدم
\nstring.Emptyبدلاً من الأقواس الفارغة - فهذا يحسن قابلية القراءة ويتوافق مع أفضل ممارسات C#.
\n\n
الخطأ رقم 2: التهيئة في المُنشئ دون مراعاة سلسلة الاستدعاءات
\n\nخطأ شائع آخر هو تعيين القيمة الافتراضية C# فقط في المُنشئ، مع تجاهل مُهيئات الخصائص. قد يؤدي هذا إلى ارتباك، خاصة عند التعامل مع الوراثة.
\n\npublic class BaseClass\n{\n public int Value { get; set; }\n\n public BaseClass()\n {\n Value = 10;\n }\n}\n\npublic class DerivedClass : BaseClass\n{\n public DerivedClass()\n {\n // Value بالفعل = 10، لكن يمكننا إعادة تعيينه\n }\n}\n\nالمشكلة: إذا أضفت مُهيئًا للخاصية Value و تركت التعيين في المُنشئ، فقد يفاجئك ترتيب التنفيذ. يتم تنفيذ المُهيئات قبل جسم مُنشئ الكلاس الأساسي، ولكن بعد استدعاء مُنشئ الكلاس المشتق.
كيف تتجنب ذلك؟
\nاختر طريقة واحدة: إما المُهيئ أو المُنشئ. من الأفضل تفضيل مُهيئات الخصائص التلقائية C# لأنها أكثر قابلية للتنبؤ وإيجازًا.
\n\npublic class BaseClass\n{\n public int Value { get; set; } = 10; // مصدر واحد للحقيقة\n}\n\n\n\n
الخطأ رقم 3: استخدام الحقول للقراءة فقط بدلاً من الخصائص التلقائية
\n\nبعض المطورين، في محاولة لتعيين قيمة ابتدائية، يتخلون عن الخصائص التلقائية ويستخدمون الحقول العامة:
\n\npublic class Config\n{\n public readonly int MaxRetries = 3; // خطأ: انتهاك للتغليف\n}\n\nهذه ممارسة سيئة. الحقول تنتهك مبدأ التغليف - لن تتمكن من إضافة منطق إلى getter/setter دون تغيير API. بالإضافة إلى ذلك، عند التسلسل أو الاستخدام في WPF/Blazor، سيؤدي ذلك إلى مشاكل.
\n\nالنهج الصحيح
\nاستخدم الخصائص التلقائية مع التهيئة أو خصائص init-only في C# 9: