فحص الأنواع في C#: typeof، GetType أم is؟ كيف لا تتوه بين ثلاثة خيارات
\n\nكل مطور C#، عاجلاً أم آجلاً، يواجه الحاجة للتحقق من نوع كائن. قد يبدو الأمر بسيطاً؟ ولكن عندما يكون أمامك ثلاثة خيارات — typeof، GetType() و is — تتشتت العيون ويتبادر إلى الذهن سؤال منطقي: "أي واحد منهم أختار؟".
هذه المقالة ليست مجرد خلاصة جافة من التوثيق. سنحلل كل نهج بأمثلة حقيقية، ونكشف عن المطبات الخفية ونقدم توصيات واضحة. بعد القراءة، ستتوقف عن التخمين وستعرف بالضبط أي أداة تستخدم في موقف معين. هيا بنا!
\n\nلماذا نحتاج أصلاً إلى فحص الأنواع في C#؟
\n\nقبل الغوص في التفاصيل، دعنا نتذكر لماذا نحتاج إلى ذلك. C# هي لغة شديدة التحديد (strictly typed)، لكن هذا لا يلغي المواقف التي يكون فيها نوع الكائن معروفاً فقط أثناء التنفيذ. إليك السيناريوهات الأكثر شيوعاً:
\n\n- \n
- العمل مع الواجهات والفئات الأساسية: تستلم كائنًا كـ
objectأو نوع أساسي، وتحتاج إلى معرفة "شخصيته" الحقيقية. \n - التسلسل وإلغاء التسلسل: JSON أو XML يأتيان كسلسلة نصية، وتحتاج إلى استعادة النوع المحدد. \n
- الانعكاس (Reflection): عندما تنشئ كائنات ديناميكياً أو تستدعي دوالاً، مع معرفة اسم النوع فقط. \n
- تسجيل الأحداث وتصحيح الأخطاء: أحياناً تحتاج فقط إلى إخراج النوع الذي تعمل معه في السجل. \n
وهنا يظهر أبطالنا الثلاثة على المسرح. دعنا نتعرف على كل منهم عن قرب.
\n\ntypeof — نظرة ثابتة إلى المستقبل
\n\ntypeof هو عامل (operator) يعيد كائن System.Type لنوع معروف في مرحلة التجميع. يعمل كخدمة استعلام: "قل لي اسم الفئة، وسأعطيك كل المعلومات عنها".
كيف يعمل:
\nType stringType = typeof(string);\nConsole.WriteLine(stringType.FullName); // الإخراج: System.String\n\nType intType = typeof(int);\nConsole.WriteLine(intType.FullName); // الإخراج: System.Int32\n\nالميزة الأساسية: typeof لا يتطلب نسخة (instance) من الكائن. إنها عملية ثابتة. أنت تقول للمترجم: "لدي نوع MyClass، أعطني بياناته الوصفية".
متى تستخدم:
\n- \n
- عندما تحتاج إلى النوع باسم الفئة، وليس بناءً على كائن. \n
- في السمات (attributes) (مثل:
[AttributeUsage(typeof(MyAttribute))]). \n - في الأنواع العامة (generics):
typeof(List<>). \n
المطب الخفي: typeof يعيد دائماً النوع الدقيق الذي حددته في الكود. لا يعرف عن الوراثة. إذا كان لديك class Dog : Animal { }، فإن typeof(Animal) لن يصبح أبداً typeof(Dog).
GetType() — تحقيق ديناميكي
\n\nعلى عكس typeof، يتم استدعاء الدالة GetType() على نسخة الكائن. تأخذ الكائن الحقيقي الموجود في الذاكرة وتقول: "آه، هكذا أنت في الحقيقة!".
مثال:
\nobject obj = "مرحباً، أيها العالم!";\nType typeOfObj = obj.GetType();\nConsole.WriteLine(typeOfObj.FullName); // الإخراج: System.String\n\n// والآن الحيلة:\nobject obj2 = 42;\nType typeOfObj2 = obj2.GetType();\nConsole.WriteLine(typeOfObj2.FullName); // الإخراج: System.Int32\n\nلاحظ: المتغير obj تم تعريفه كـ object، لكن GetType() "ترى" من خلال هذا الغلاف وتعيد System.String. هذا هو التحديد الديناميكي للنوع.
متى تستخدم:
\n- \n
- عندما تحتاج إلى معرفة النوع الدقيق للكائن أثناء التنفيذ. \n
- لمقارنة الأنواع:
obj.GetType() == typeof(MyClass). \n