المندوبون والأحداث
في لغة سي شارب، تُعد المندوبون (Delegates) والأحداث (Events) من الأدوات الأساسية لإنشاء برامج مرنة وقابلة للتوسع. المندوب هو مؤشر دالة آمن من حيث النوع، يتيح تمرير الأساليب كوسائط، تخزينها واستدعاؤها ديناميكياً، مما يسمح بتصميم أنماط برمجية عالية المرونة. أما الأحداث، فتُبنى على المندوبون لتوفير نموذج ناشر-مشترك، بحيث يمكن للأشياء الإبلاغ عن تغييراتها أو حدوث أحداث معينة دون ربط مباشر مع المستمعين، وهو ما يعزز قابلية صيانة النظام وسهولة تطويره.
تُستخدم المندوبون والأحداث في سي شارب لإنشاء إشعارات مخصصة، بناء أنظمة الإضافات (Plugins)، التفاعل مع واجهات المستخدم، تسجيل النشاطات، وجدولة المهام. من خلال المندوبون يمكن تمرير المراجع إلى الأساليب ومعالجتها ديناميكياً، بينما تتيح الأحداث إدارة الاشتراكات بشكل آمن، مما يضمن استجابة متعددة للمستمعين دون تعارض. في هذا الدرس، سيتعلم القارئ كيفية تعريف المندوبون، إنشاء الأحداث، الاشتراك بها، واستدعاؤها بطريقة سليمة، مع الالتزام بمبادئ البرمجة الكائنية، الهياكل البيانية، والخوارزميات الفعالة.
باستيعاب هذه المفاهيم، سيتمكن المطور من تطبيق أنماط التصميم مثل Observer وCommand، وبناء أنظمة برمجية تعتمد على الأحداث في بيئات عمل حقيقية، مع تجنب المشاكل الشائعة مثل تسرب الذاكرة أو سوء معالجة الاستثناءات.
مثال أساسي
textusing System;
namespace DelegatesAndEventsDemo
{
// تعريف نوع المندوب
public delegate void NotificationHandler(string message);
// فئة الناشر تحتوي على الحدث
public class Publisher
{
public event NotificationHandler Notify;
public void SendNotification(string message)
{
// استدعاء الحدث بأمان
Notify?.Invoke(message);
}
}
// فئة المشترك
public class Subscriber
{
private string _name;
public Subscriber(string name)
{
_name = name;
}
public void OnNotificationReceived(string message)
{
Console.WriteLine($"{_name} استلم الرسالة: {message}");
}
}
class Program
{
static void Main(string[] args)
{
Publisher publisher = new Publisher();
Subscriber alice = new Subscriber("Alice");
Subscriber bob = new Subscriber("Bob");
// الاشتراك في الحدث
publisher.Notify += alice.OnNotificationReceived;
publisher.Notify += bob.OnNotificationReceived;
publisher.SendNotification("مرحباً بالمشتركين!");
// إلغاء اشتراك Bob وإرسال رسالة ثانية
publisher.Notify -= bob.OnNotificationReceived;
publisher.SendNotification("الرسالة الثانية");
Console.ReadLine();
}
}
يوضح المثال أعلاه تعريف المندوب NotificationHandler
الذي يحدد توقيع الدالة لتلقي سلسلة نصية، مما يضمن أمان النوع عند الاشتراك بالحدث. فئة Publisher
تحتوي على الحدث Notify
وتستخدم عامل الاستدعاء الشرطي ?.
لضمان استدعاء الحدث بأمان فقط عند وجود مشتركين.
فئة Subscriber
تمثل المستمعين، كل كائن منها يمتلك أسلوب OnNotificationReceived
الذي يطابق توقيع المندوب. في البرنامج الرئيسي، يتم إنشاء كائنات الناشر والمشتركين والاشتراك بالحدث، وعند استدعاء SendNotification
يتم استدعاء كل الطرق المشتركة بالتتابع. كما يظهر المثال كيفية إلغاء الاشتراك باستخدام -=
لتجنب الاحتفاظ بالمراجع غير الضرورية، وهو ما يمنع تسرب الذاكرة.
يمثل هذا المثال عدة مفاهيم متقدمة في سي شارب: المندوبون الآمنة من حيث النوع، التغليف بواسطة الأحداث، وفصل المكونات لتحقيق تصميم مرن وقابل للصيانة، مع استخدام أفضل الممارسات مثل الاستدعاء الشرطي للحدث لضمان سلامة الذاكرة.
مثال عملي
textusing System;
using System.Collections.Generic;
namespace DelegatesAndEventsAdvanced
{
// تعريف مندوب لمعالجة البيانات
public delegate void DataProcessedHandler(int result);
// فئة معالجة البيانات تحاكي الحسابات وتبلغ المشتركين
public class DataProcessor
{
public event DataProcessedHandler DataProcessed;
public void ProcessData(List<int> data)
{
int sum = 0;
foreach (var num in data)
{
if (num < 0)
{
Console.WriteLine("تجاوز الرقم غير صالح: " + num);
continue; // معالجة الأخطاء
}
sum += num;
}
// إعلام المشتركين بالنتيجة
DataProcessed?.Invoke(sum);
}
}
// فئة سجل الأحداث
public class Logger
{
public void LogResult(int result)
{
Console.WriteLine($"تسجيل النتيجة: {result}");
}
}
// فئة التنبيهات
public class Notifier
{
public void SendAlert(int result)
{
if (result > 50)
Console.WriteLine("تنبيه! النتيجة تجاوزت الحد: " + result);
}
}
class Program
{
static void Main(string[] args)
{
DataProcessor processor = new DataProcessor();
Logger logger = new Logger();
Notifier notifier = new Notifier();
// الاشتراك في الحدث
processor.DataProcessed += logger.LogResult;
processor.DataProcessed += notifier.SendAlert;
List<int> sampleData = new List<int> { 10, 20, 30, -5 };
processor.ProcessData(sampleData);
Console.ReadLine();
}
}
يعرض هذا المثال المتقدم تطبيق المندوبون والأحداث في سيناريو عملي. فئة DataProcessor
تقوم بحساب مجموع الأرقام في قائمة مع معالجة القيم السالبة لتجنب الأخطاء. الحدث DataProcessed
يسمح لمستمعين متعددين مثل Logger
وNotifier
بالاستجابة للنتيجة دون أن يعرف المنشئ عددهم أو طبيعة عملياتهم، وهو نموذج المراقب (Observer Pattern).
كل مستمع مسؤول عن مهمة محددة: Logger
يسجل النتائج، وNotifier
يرسل التنبيهات عند تجاوز القيمة حد معين. استخدام المندوبون يحقق توسعاً ونظاماً مرناً. يظهر المثال أفضل الممارسات مثل الاستدعاء الشرطي للحدث، الالتزام بمبدأ المسؤولية الواحدة، وفصل المكونات مع معالجة الأخطاء بأمان. هذه الأنماط قابلة للتطبيق في أنظمة التحليل القائمة على الأحداث، وأطر الإضافات، والإشعارات غير المتزامنة.
أفضل الممارسات والفخاخ الشائعة في سي شارب:
عند العمل مع المندوبون والأحداث، يجب الالتزام باستخدام المندوبون الآمنة من حيث النوع، والتغليف بالأحداث لضمان إدارة الاشتراكات. استخدام الاستدعاء الشرطي للحدث يمنع حدوث NullReferenceException. يجب إلغاء الاشتراكات عند عدم الحاجة لتجنب تسرب الذاكرة، خصوصاً في الكائنات طويلة العمر.
من الأخطاء الشائعة: الاشتراك بأساليب مجهولة دون إلغاء، مما يعيق جمع القمامة، أو استدعاء الأحداث على الخيط الرئيسي لفترات طويلة، مما يعيق استجابة التطبيق. يجب الانتباه لترتيب استدعاء الأحداث، وسلامة الخيوط، والتعامل مع استثناءات المشتركين للحفاظ على استقرار النظام. لتحسين الأداء، قلل من سلاسل المندوبون في الأحداث عالية التردد، وتجنب إنشاء كائنات بشكل متكرر داخل حلقات الأحداث. تحقق من صحة البيانات المرسلة عبر الأحداث لتجنب تسرب الحالة الداخلية. أدوات Visual Studio للتحليل والأداء تساعد على اكتشاف التسربات والمشاكل المتعلقة بالأحداث.
📊 جدول مرجعي
سي شارب Element/Concept | Description | Usage Example |
---|---|---|
مندوب | مؤشر دالة آمن من حيث النوع، يسمح بالاستدعاء الديناميكي | public delegate void MyDelegate(int x); |
حدث | آلية إعلام مبنية على المندوبون | public event MyDelegate MyEvent; |
الاشتراك | إضافة أسلوب إلى قائمة استدعاء الحدث | myPublisher.MyEvent += mySubscriber.MyMethod; |
إلغاء الاشتراك | إزالة أسلوب من الحدث لمنع تسرب الذاكرة | myPublisher.MyEvent -= mySubscriber.MyMethod; |
استدعاء شرطي | استدعاء الحدث بأمان عند وجود مشتركين | MyEvent?.Invoke(42); |
مندوب مجهول | تعريف المندوب داخلياً | myPublisher.MyEvent += (x) => Console.WriteLine(x); |
الخلاصة والخطوات التالية:
المندوبون والأحداث أدوات قوية في سي شارب لبناء تطبيقات مرنة وقابلة للصيانة. النقاط الأساسية تشمل تعريف المندوبون الآمنة، إعلان الأحداث، إدارة الاشتراكات، واستدعاء الأحداث بأمان. تمكن هذه المفاهيم من تنفيذ أنماط المراقب، وآليات الاستدعاء العكسي، وتصميم أنظمة قائمة على الأحداث.
للتوسع، يُنصح بدراسة الأنماط المتقدمة للأحداث، البرمجة غير المتزامنة باستخدام async/await، ودمج المندوبون مع LINQ والمبادئ البرمجية الوظيفية. تطبيق هذه المفاهيم في المشاريع العملية مثل أنظمة الإشعارات وأطر الإضافات يعزز الفهم العملي. الموارد المفيدة تشمل وثائق Microsoft الرسمية، كتب تصميم الأنماط، والمشاريع مفتوحة المصدر. إتقان المندوبون والأحداث يمثل خطوة أساسية للانتقال من مستوى سي شارب الأساسي إلى تصميم أنظمة برمجية معمارية قوية وآمنة.
🧠 اختبر معرفتك
Test Your Knowledge
Test your understanding of this topic with practical questions.
📝 التعليمات
- اقرأ كل سؤال بعناية
- اختر أفضل إجابة لكل سؤال
- يمكنك إعادة الاختبار عدة مرات كما تريد
- سيتم عرض تقدمك في الأعلى