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

الـ Delegates والأحداث

جزء من قسم البرمجة كائنية التوجه في رحلة C# على Coddy. الدرس 43 من 70.

إن delegate هو نوع يمثّل مرجعًا إلى طريقة. فكّر فيه كمتغيّر يحتفظ بطريقة بدلًا من البيانات. يتيح لك ذلك تمرير الطرق كوسائط، وتخزينها في مجموعات، واستدعاءها ديناميكيًا.

تُعرِّف delegate من خلال تحديد توقيع الأسلوب الذي يمكنه الإشارة إليه:

public delegate void Notify(string message);

public class Publisher
{
    public void SendAlert(string msg) => Console.WriteLine("Alert: " + msg);
}

// الاستخدام
Notify notifier = new Publisher().SendAlert;
notifier("System started");  // تنبيه: بدأ النظام

الأحداث تعتمد على المفوَّضات لتنفيذ نمط النشر والاشتراك. يطلق class حدثًا، ويمكن لـ class أخرى الاشتراك لتلقي الإشعارات. تقيّد الكلمة المفتاحية event كيفية استخدام المفوَّض، إذ لا يمكن للمشتركين سوى إضافة معالجات أو إزالتها، وليس استدعاء الحدث مباشرةً.

public class Button
{
    public event Action Clicked;
    
    public void Click()
    {
        Clicked?.Invoke();  // أبلغ جميع المشتركين
    }
}

// الاشتراك
Button btn = new Button();
btn.Clicked += () => Console.WriteLine("Button was clicked!");
btn.Click();  // تم النقر على الزر!

يشترك المعامل += في handler، بينما يلغي -= الاشتراك. يستدعي النمط ?.Invoke() event بأمان فقط إذا كان هناك subscribers. تُعد event أساسية لتطبيقات GUI ومحركات الألعاب وأي نظام تحتاج فيه الكائنات إلى الاستجابة للتغييرات دون ترابط وثيق.

challenge icon

التحدي

سهل

لنبنِ نظامًا لمراقبة درجة الحرارة يستخدم delegates وevents لإخطار subscribers كلما تغيرت درجة الحرارة. هذا مثال كلاسيكي على publish-subscribe pattern الذي تتيحه events بأناقة كبيرة.

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

  • TemperatureMonitor.cs: أنشئ فئة TemperatureMonitor في مساحة الأسماء Monitoring لتعمل باعتبارها الناشر. يجب أن يتضمن monitor الخاص بك ما يلي:
    • امتلاك field خاص لتخزين درجة الحرارة الحالية
    • Declare event باستخدام Action<int> يسمى TemperatureChanged ويتم إطلاقه كلما تم تحديث درجة الحرارة
    • امتلاك الخاصية Temperature (من النوع int)، بحيث يحدّث setter الـ field الخاص ويرفع event باستخدام قيمة درجة الحرارة الجديدة
    تذكّر استخدام نمط ?.Invoke() لرفع event بأمان فقط عند وجود subscribers.
  • Program.cs: في الملف الرئيسي، أنشئ TemperatureMonitor واشترك بمعالجي event مختلفين في event TemperatureChanged الخاص به:
    • معالج يطبع: Alert: Temperature is now {value} degrees
    • معالج آخر يطبع: Logged: {value}
    بعد Subscribe لكلا المعالجين، اضبط درجة الحرارة مرتين باستخدام القيم المُدخلة. في كل مرة تضبط فيها درجة الحرارة، يجب أن يستجيب كلا المعالجين.

ستتلقى مُدخلين:

  • قيمة درجة الحرارة الأولى (عدد صحيح)
  • قيمة درجة الحرارة الثانية (عدد صحيح)

على سبيل المثال، إذا كانت المدخلات 25 و30، فيجب أن يكون الناتج:

Alert: Temperature is now 25 degrees
Logged: 25
Alert: Temperature is now 30 degrees
Logged: 30

لاحظ كيف تُخطر خاصية Temperature تلقائيًا جميع subscribers عند ضبطها؛ فلا يحتاج monitor إلى معرفة أي شيء عن المستمعين. هذه هي روعة النهج القائم على event!

جرّب بنفسك

using System;
using Monitoring;

class Program
{
    public static void Main(string[] args)
    {
        // اقرأ المدخلات
        int temp1 = Convert.ToInt32(Console.ReadLine());
        int temp2 = Convert.ToInt32(Console.ReadLine());

        // TODO: أنشئ مثيلاً من TemperatureMonitor

        // TODO: Subscribe a handler that prints: "Alert: Temperature is now {value} degrees"

        // TODO: اشترك معالجًا آخر يطبع: "Logged: {value}"

        // TODO: عيّن درجة الحرارة إلى temp1

        // TODO: عيّن درجة الحرارة إلى temp2
    }
}
quiz iconاختبر نفسك

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

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم C# عبر الإنترنت