في C، غالبًا ما تُستخدم المعلمة "T" لتحديد الوظائف التي تأخذ أي نوع من الأنواع. يتم استخدامها لكتابة فئات وأساليب عامة يمكنها العمل مع أي نوع من البيانات ، مع الحفاظ على أمان النوع الصارم. سنناقش كيفية عملها وكيفية استخدامها.
كيف يعمل؟
المتغير "T" الذي ربما رأيته في بعض تعريفات الطرق يسمى معلمة النوع العام ، أو ببساطة "عام". يمكن استخدام الطرق العامة التي تستخدم T مع أي نوع ، مما يسهل تحديد الفئات والطرق التي لا تهتم بالبيانات التي يتعاملون معها ولكنهم يريدون الاحتفاظ بها.
على سبيل المثال ، تستفيد المجموعات من الأدوية الجنيسة ، حتى يتمكنوا من التعامل مع أي شيء يرميها المستخدم عليها. لا يوجد تعريف مختلف لـ
List
و
List
؛ بدلاً من ذلك ، هناك تعريف واحد لـ
List.
من الناحية العملية ، يبدو هذا كما يلي. على الرغم من أن هذه فئة وليست طريقة ، فلا يزال بإمكانك تمرير معلمات النوع لها باستخدام صيغة الأقواس. ثم ، في أي مكان تريد الإشارة فيه إلى شيء من هذا النوع ، يمكنك ببساطة استبدال المعلمة بدلاً من ذلك.

يسمح لك وضع أي شيء بين قوسين باستخدام هذا الاسم بدلاً من نوع صالح ، في أي مكان في تعريف الفئة أو الطريقة التي تستخدم هذا المعامل. إذا تخيلت
GenericList
، في أي مكان ستكتب
int
كنوع بدلاً من ذلك ستكتب
T، واترك الأمر للمستخدم ليخبر هذه الفئة بالنوع الذي يجب استخدامه.
الأمر بهذه البساطة حقًا. بالنسبة إلى
GenericList
، فإن الكود أعلاه مكافئ وظيفيًا لكتابة ما يلي ، على الرغم من أنه يجب ملاحظة أن هذا التعريف لا يتضمن
GenericList، لأن كل شيء بين الأقواس عبارة عن معلمات كتابة ، ولا يمكن استخدام العناصر الأولية كأسماء أنواع. بالنسبة للفصل الذي لا يستخدم أي معلمات ، مثل هذه ، يتم تعريفه كالمعتاد بدون أقواس.

يمكنك في الواقع تسمية هذا المتغير T بأي شيء ، على الرغم من أنه من الشائع البدء به على الأقل بـ "T." إذا كانت لديك وظيفة تحتاج إلى وسيطات متعددة الأنواع ، فيمكنك تسميتها بشكل مختلف ، مثل "TOutput" أو "TInput". يتم استخدام هذا كثيرًا في تعريفات التفويض ، وفي القواميس حيث لديك TKey و TValue.

بالطبع ، يمكنك أيضًا استخدام الأدوية الجنيسة في الأساليب ، وكذلك الواجهات والمفوضين. إنها تعمل بنفس الطريقة ، ويمكنك حتى تمرير معلمة النوع كمعامل نوع إلى وظيفة أخرى.

على وجه الخصوص ، يمكنك استخدام معلمة النوع في المعلمات الفعلية للوظيفة. ستظل بحاجة إلى وضعه بين قوسين ، وإلا فسيكون نوعًا غير صالح فقط ، ولكن يمكنك استخدام المعلمة في أي مكان في تعريف هذه الطريقة.

إنها مفيدة بشكل خاص للمندوبين ، لأنه يمكنك استخدامها لقبول الوظائف ذات المعلمات المتغيرة.
نوع القيود
العوامل العامة رائعة ، لكنها يمكن أن تسبب بعض المشكلات عندما يُسمح للوظيفة بأخذ أي نوع ممكن ترميه. في بعض الأحيان ، من الأفضل وضع بعض القيود على الاستخدام.
يتم ذلك باستخدام
حيث T:
بناء الجملة. أبسط شكل لهذا هو
حيث T: ClassName
، مما يضمن أن المعلمة T يجب أن تكون أو مشتقة من النوع المحدد
ClassName
هذا يتيح النوع- تعدد الأشكال الآمن ، مثل هذه الوظيفة التي تأخذ أي نوع من الفاكهة ، وترجع
قائمة
، بدلاً من
قائمة، والتي ستكون صحيحة من الناحية الفنية ولكن تفقد نوع المعلومات القيمة.

يمكنك أن ترى أنه إذا حاولنا استخدام هذه الوظيفة مع أي شيء ليس فاكهة ، فإن المترجم سوف يصرخ عليك.

بخلاف الميراث البسيط ، هناك بعض القيود المفيدة:
-
حيث T: InterfaceName
- مثلT: ClassNameولكن تأكد من أن وسيطة النوع تنفذ الواجهة المحددة.
-
حيث T: class- يضمن أن وسيطة النوع هي نوع مرجعي.
-
حيث T: Struct- يضمن أن وسيطة النوع هي نوع قيمة غير قابل للصفاء.
-
حيث T: notnull- يجب أن تكون وسيطة النوع من النوع non-nullable.
-
حيث T: new ()- يجب أن تكون وسيطة النوع قادرة على الإنشاء بدون معلمات.
-
حيث T: TOther
- يجب أن تكون وسيطة النوعT
أو مشتقة من وسيطة النوعTOther.
يمكنك تحديد قيود متعددة في قائمة مفصولة بفواصل.