الـ 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 ومحركات الألعاب وأي نظام تحتاج فيه الكائنات إلى الاستجابة للتغييرات دون ترابط وثيق.
التحدي
سهللنبنِ نظامًا لمراقبة درجة الحرارة يستخدم 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 مختلفين في eventTemperatureChangedالخاص به:- معالج يطبع:
Alert: Temperature is now {value} degrees - معالج آخر يطبع:
Logged: {value}
- معالج يطبع:
ستتلقى مُدخلين:
- قيمة درجة الحرارة الأولى (عدد صحيح)
- قيمة درجة الحرارة الثانية (عدد صحيح)
على سبيل المثال، إذا كانت المدخلات 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
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات OOP
الملفات الخارجيةNamespaces والتوجيهاتمقدمة في Classes و Objectsالكلمة المفتاحية 'this'Methods والمعاملاتFields مقابل PropertiesConstructorsObject Initializersمراجعة - آلة حاسبة بسيطة4الوراثة
صيغة الوراثة الأساسية (:)الكلمة المفتاحية 'base'الكلمات المفتاحية Virtual و Overrideالأصناف المختومة (Sealed Classes)الفئة الأساسية 'object'مراجعة - هيكلية الموظفين7ميزات متقدمة
تحميل العوامل (Operator Overloading)المفهرسات (Indexers (this[]))إعادة تعريف ()ToStringدوال التوسعة (Extension Methods)ملخص - Custom List2الخصائص والأعضاء الساكنة (Static Members)
الخصائص المطبقة تلقائيًا (Auto-Implemented Properties)خصائص القراءة فقط والكتابة فقطالحقول والدوال الساكنة (Static)الفئات الساكنة (Static Classes)الأعضاء ذات البنية التعبيرية (Expression-Bodied Members)5تعدد الأشكال والواجهات (Polymorphism & Interfaces)
تعدد الأشكال: وقت التجميع مقابل وقت التشغيلالواجهة مقابل الفئة المجردة (Abstract Class)الواجهات المتعددةالواجهات الصريحةUpcasting و Downcastingملخص - حاسبة الأشكال8مفاهيم البرمجة كائنية التوجه (OOP) المتقدمة
التركيب بدلاً من الوراثةالـ Generics (الأصناف والدوال)الـ Delegates والأحداثالـ Attributes والـ Reflectionواجهة IDisposable وجملة usingأساسيات Dependency Injectionتدرّب بنفسك: مترجم C# عبر الإنترنت