تهيئة الخصائص التلقائية في C#: أهم 5 أخطاء ودليل شامل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا حظي سؤال الخصائص التلقائية بآلاف المشاهدات؟

\n\n

إذا كنت قد كتبت كودًا بلغة C# من قبل، فبالتأكيد واجهت سؤالًا بسيطًا لكنه مهم: "كيف يتم تعيين القيمة الابتدائية للخاصية التلقائية بشكل صحيح؟". هذا السؤال على Stack Overflow حصد عشرات الآلاف من المشاهدات، وهذا ليس بدون سبب. فالبساطة الظاهرية تخفي العديد من المزالق.

\n\n

تخيل: أنت تنشئ كلاس User، وتريد أن تكون الخاصية Name افتراضيًا ليست null، بل سلسلة فارغة. يبدو الأمر بسيطًا، أليس كذلك؟ لكن في الواقع، يقع المطورون في أخطاء نموذجية عند تهيئة خصائص C# تؤدي إلى NullReferenceException أو سلوك غير متوقع.

\n\n

في هذه المقالة، سنستعرض أهم 5 أخطاء ونوضح كيفية تجنبها. ستتعرف على الأساليب الحديثة - من C# 6 إلى C# 12 - وستفهم أي طريقة تختار لمشروعك.

\n\n
\n\n

الخطأ رقم 1: تجاهل تهيئة الخصائص التلقائية

\n\n

الخطأ الأكثر شيوعًا هو عدم تعيين قيمة ابتدائية للأنواع المرجعية. كثير من المبتدئين يكتبون:

\n\n
public 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\n

كيف تصلح ذلك؟

\n

قم دائمًا بتعيين مُهيئ الخاصية التلقائية C# بشكل صريح. أسهل طريقة هي استخدام صياغة C# 6:

\n\n
public 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

نصيحة: استخدم string.Empty بدلاً من الأقواس الفارغة - فهذا يحسن قابلية القراءة ويتوافق مع أفضل ممارسات C#.

\n
\n\n
\n\n

الخطأ رقم 2: التهيئة في المُنشئ دون مراعاة سلسلة الاستدعاءات

\n\n

خطأ شائع آخر هو تعيين القيمة الافتراضية C# فقط في المُنشئ، مع تجاهل مُهيئات الخصائص. قد يؤدي هذا إلى ارتباك، خاصة عند التعامل مع الوراثة.

\n\n
public 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\n

كيف تتجنب ذلك؟

\n

اختر طريقة واحدة: إما المُهيئ أو المُنشئ. من الأفضل تفضيل مُهيئات الخصائص التلقائية C# لأنها أكثر قابلية للتنبؤ وإيجازًا.

\n\n
public class BaseClass\n{\n    public int Value { get; set; } = 10; // مصدر واحد للحقيقة\n}
\n\n
\n\n

الخطأ رقم 3: استخدام الحقول للقراءة فقط بدلاً من الخصائص التلقائية

\n\n

بعض المطورين، في محاولة لتعيين قيمة ابتدائية، يتخلون عن الخصائص التلقائية ويستخدمون الحقول العامة:

\n\n
public class Config\n{\n    public readonly int MaxRetries = 3; // خطأ: انتهاك للتغليف\n}
\n\n

هذه ممارسة سيئة. الحقول تنتهك مبدأ التغليف - لن تتمكن من إضافة منطق إلى getter/setter دون تغيير API. بالإضافة إلى ذلك، عند التسلسل أو الاستخدام في WPF/Blazor، سيؤدي ذلك إلى مشاكل.

\n\n

النهج الصحيح

\n

استخدم الخصائص التلقائية مع التهيئة أو خصائص init-only في C# 9:

المدونات

توصيات الكتب