Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

الـ Generics (الأصناف والدوال)

جزء من قسم Object Oriented Programming في رحلة C# على Coddy — الدرس 42 من 70.

تسمح لك الأنواع العامة (Generics) بكتابة فئات (classes) وطرق (methods) تعمل مع أي نوع بيانات مع الحفاظ على سلامة النوع (type safety). فبدلاً من كتابة فئات منفصلة لكل من IntList و StringList و DoubleList، يمكنك كتابة فئة عامة واحدة تتعامل معها جميعاً.

يستخدم الصنف العام (generic class) معامل نوع، عادةً ما يسمى T، محاطاً بأقواس زاوية:

public class Box<T>
{
    private T content;
    
    public void Store(T item) => content = item;
    public T Retrieve() => content;
}

// الاستخدام مع أنواع مختلفة
Box<int> intBox = new Box<int>();
intBox.Store(42);

Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");

عندما تقوم بإنشاء Box<int>، يقوم المترجم باستبدال كل T بـ int. يوفر هذا فحصاً للأنواع في وقت الترجمة - لا يمكنك تخزين سلسلة نصية عن طريق الخطأ في صندوق int.

تعمل الدوال العامة (Generic methods) بشكل مشابه، مما يسمح لدالة واحدة بالعمل على أنواع مختلفة:

public static void Swap<T>(ref T a, ref T b)
{
    T temp = a;
    a = b;
    b = temp;
}

int x = 1, y = 2;
Swap(ref x, ref y);  // x=2, y=1

يستنتج المترجم النوع من المعاملات، لذا لا تحتاج إلى كتابة Swap<int> بشكل صريح. تعد الـ Generics هي الأساس لمجموعات مثل List<T> و Dictionary<TKey, TValue>، مما يتيح كوداً قابلاً لإعادة الاستخدام وآمناً من حيث النوع.

challenge icon

التحدي

سهل

لنقم ببناء نظام Storage<T> عام يمكنه الاحتفاظ بالعناصر من أي نوع وإدارتها. ستقوم بإنشاء فئة حاوية قابلة لإعادة الاستخدام توضح قوة الأنواع العامة (generics) - اكتبها مرة واحدة، واستخدمها مع الأعداد الصحيحة، أو النصوص، أو أي نوع آخر!

ستقوم بتنظيم الكود الخاص بك عبر ملفين:

  • Storage.cs: أنشئ فئة Storage<T> عامة داخل مساحة الأسماء DataStorage. يجب أن تقوم حاوية التخزين الخاصة بك بما يلي:
    • امتلاك مصفوفة خاصة من النوع T للاحتفاظ بالعناصر وخاصية Count لتتبع عدد العناصر المخزنة.
    • قبول سعة (capacity) في منشئ الفئة (constructor) لتهيئة المصفوفة الداخلية.
    • امتلاك طريقة Add(T item) تضيف عنصراً إذا كانت هناك مساحة متوفرة.
    • امتلاك طريقة Get(int index) تعيد العنصر الموجود في الفهرس المحدد.
    • امتلاك طريقة GetAll() تعيد جميع العناصر المخزنة مدمجة بفاصلة ", ".
  • Program.cs: في ملفك الرئيسي، قم بتوضيح عمل فئتك العامة مع نوعين مختلفين. أنشئ Storage<int> و Storage<string>، وأضف عناصر إلى كل منهما، وأظهر أن نفس الفئة تعمل بسلاسة مع كلا النوعين.

ستتلقى أربعة مدخلات:

  • العدد الصحيح الأول لتخزينه
  • العدد الصحيح الثاني لتخزينه
  • النص الأول لتخزينه
  • النص الثاني لتخزينه

أنشئ مخزناً للأعداد الصحيحة بسعة 5 ومخزناً للنصوص بسعة 5. أضف العددين الصحيحين إلى مخزن الأعداد الصحيحة والنصين إلى مخزن النصوص.

اطبع المخرجات بهذا التنسيق:

Int storage: {GetAll()}
Int count: {Count}
First int: {Get(0)}
String storage: {GetAll()}
String count: {Count}
First string: {Get(0)}

على سبيل المثال، إذا كانت المدخلات هي 42، و 100، و Hello، و World، يجب أن تكون المخرجات:

Int storage: 42, 100
Int count: 2
First int: 42
String storage: Hello, World
String count: 2
First string: Hello

لاحظ كيف كتبت فئة Storage<T> مرة واحدة، ولكنها تعمل بشكل مثالي مع كل من int و string - هذا هو سحر الأنواع العامة (generics)! يضمن المترجم (compiler) سلامة النوع، لذا لا يمكنك إضافة نص بالخطأ إلى مخزن الأعداد الصحيحة الخاص بك.

ورقة مرجعية

تسمح لك الأنواع العامة (Generics) بكتابة فئات (classes) وطرق (methods) تعمل مع أي نوع بيانات مع الحفاظ على سلامة النوع (type safety).

تستخدم الفئة العامة معامل نوع (عادةً ما يكون T) محاطاً بأقواس زاوية:

public class Box<T>
{
    private T content;
    
    public void Store(T item) => content = item;
    public T Retrieve() => content;
}

عند إنشاء مثيل (instance)، حدد النوع الذي سيحل محل T:

Box<int> intBox = new Box<int>();
intBox.Store(42);

Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");

تسمح الطرق العامة (Generic methods) لطريقة واحدة بالعمل على أنواع مختلفة:

public static void Swap<T>(ref T a, ref T b)
{
    T temp = a;
    a = b;
    b = temp;
}

int x = 1, y = 2;
Swap(ref x, ref y);  // Compiler infers type from arguments

توفر الأنواع العامة (Generics) فحصاً للنوع في وقت التجميع (compile-time) وهي الأساس لمجموعات مثل List<T> و Dictionary<TKey, TValue>.

جرّب بنفسك

using System;
using DataStorage;

class Program
{
    public static void Main(string[] args)
    {
        // قراءة المدخلات
        int num1 = Convert.ToInt32(Console.ReadLine());
        int num2 = Convert.ToInt32(Console.ReadLine());
        string str1 = Console.ReadLine();
        string str2 = Console.ReadLine();

        // TODO: بسعة 5 Storage<int> إنشاء
        
        // TODO: إضافة العددين الصحيحين إلى مخزن الأعداد الصحيحة
        
        // TODO: بسعة 5 Storage<string> إنشاء
        
        // TODO: إضافة السلسلتين النصيتين إلى مخزن النصوص
        
        // TODO: طباعة المخرجات بالتنسيق المطلوب
        // Int storage: {GetAll()}
        // Int count: {Count}
        // First int: {Get(0)}
        // String storage: {GetAll()}
        // String count: {Count}
        // First string: {Get(0)}
    }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming