در حال بارگذاری...

نماینده‌ها و رویدادها

نماینده‌ها و رویدادها در سی‌شارپ از مهم‌ترین ابزارها برای ساخت برنامه‌های انعطاف‌پذیر، ماژولار و کم‌وابسته هستند. نماینده‌ها (Delegates) نوعی اشاره‌گر نوع ایمن به متدها هستند که امکان ذخیره‌سازی و فراخوانی متدها به‌صورت داینامیک در زمان اجرا را فراهم می‌کنند. رویدادها (Events) بر پایه نماینده‌ها ساخته می‌شوند و الگوی "ناشر-مشترک" (Publisher-Subscriber) را پیاده‌سازی می‌کنند، به گونه‌ای که اشیاء می‌توانند بدون وابستگی مستقیم، از رخدادهای دیگر اشیاء مطلع شوند.
در توسعه نرم‌افزار، نماینده‌ها و رویدادها در سیستم‌های اعلان، رابط‌های کاربری، ثبت گزارش‌ها، فریم‌ورک‌های افزونه و پردازش‌های ناهمگام کاربرد فراوان دارند. با استفاده از نماینده‌ها می‌توان متدها را بدون نیاز به دانستن جزئیات پیاده‌سازی فراخوانی کرد و رویدادها امکان واکنش چندین مشترک به یک عمل مشترک را فراهم می‌آورند.
در این آموزش، شما یاد می‌گیرید که چگونه نماینده‌ها و رویدادها را تعریف، عضوگیری و فراخوانی کنید، و این مفاهیم را با اصول شیءگرایی، ساختارهای داده و الگوریتم‌ها ترکیب کنید تا مشکلات واقعی در پروژه‌های سی‌شارپ را حل کنید. همچنین به کاربرد این مفاهیم در معماری سیستم‌ها و ایجاد اجزای کم‌وابسته و قابل نگهداری پرداخته خواهد شد.

مثال پایه

text
TEXT Code
using 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("آلیس");
Subscriber bob = new Subscriber("باب");

publisher.Notify += alice.OnNotificationReceived;
publisher.Notify += bob.OnNotificationReceived;

publisher.SendNotification("سلام مشترکین!");

publisher.Notify -= bob.OnNotificationReceived;
publisher.SendNotification("پیام دوم");

Console.ReadLine();
}
}

در این مثال، نماینده NotificationHandler امضای متدهایی را که می‌توانند به رویداد مرتبط شوند مشخص می‌کند و ایمنی نوع را تضمین می‌کند. کلاس Publisher دارای رویداد Notify است که با استفاده از ?.Invoke() به‌طور ایمن فراخوانی می‌شود تا در صورت نبود مشترک، خطا رخ ندهد.
کلاس Subscriber متد OnNotificationReceived را پیاده‌سازی می‌کند که با امضای نماینده سازگار است. در متد Main، اشیاء Publisher و Subscriber ایجاد و مشترک‌گیری و لغو مشترک‌گیری رویدادها نشان داده شده است. این الگو باعث کاهش وابستگی و جلوگیری از مشکلات حافظه می‌شود و در پروژه‌های پیچیده اهمیت دارد.

مثال کاربردی

text
TEXT Code
using 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 اجازه می‌دهد بدون دانستن جزئیات پردازش، به نتیجه واکنش نشان دهند. Logger نتیجه را ثبت می‌کند و Notifier در صورت عبور از حد مشخص، هشدار می‌دهد.
این مثال الگوی Observer، اصل مسئولیت واحد (SRP)، فراخوانی ایمن رویدادها، کم‌وابستگی و بهترین شیوه‌های مدیریت خطا را نشان می‌دهد.

بهترین شیوه‌ها و اشتباهات رایج در سی‌شارپ:

  • استفاده از نماینده‌ها و رویدادهای نوع‌ایمن و encapsulated.
  • فراخوانی رویداد با ?.Invoke() برای جلوگیری از NullReferenceException.
  • حذف مشترکانی که دیگر نیاز نیستند برای جلوگیری از memory leak.
  • اجتناب از استفاده طولانی مدت از delegates ناشناس.
  • عدم انجام عملیات طولانی در thread اصلی در رویدادهای پر تکرار.
  • به حداقل رساندن تخصیص اشیاء در رویدادهای با فرکانس بالا.
  • اعتبارسنجی داده‌ها قبل از فراخوانی رویداد.

📊 جدول مرجع

سی‌شارپ Element/Concept Description Usage Example
Delegate نوع ایمن اشاره‌گر به متد public delegate void MyDelegate(int x);
Event رویداد مبتنی بر delegate public event MyDelegate MyEvent;
Subscription عضوگیری رویداد myPublisher.MyEvent += mySubscriber.MyMethod;
Unsubscription لغو عضوگیری myPublisher.MyEvent -= mySubscriber.MyMethod;
Conditional Invocation فراخوانی ایمن رویداد MyEvent?.Invoke(42);
Anonymous Delegate delegate تعریف‌شده به‌صورت inline myPublisher.MyEvent += (x) => Console.WriteLine(x);

خلاصه و گام‌های بعدی:
نماینده‌ها و رویدادها معماری انعطاف‌پذیر و کم‌وابسته‌ای در برنامه‌های سی‌شارپ فراهم می‌کنند. مفاهیم کلیدی شامل delegates نوع‌ایمن، تعریف رویدادها، عضوگیری ایمن و پیاده‌سازی الگوی Observer است.
برای پیشرفت، مطالعه برنامه‌نویسی ناهمگام، ترکیب delegates با LINQ و معماری‌های مبتنی بر رویداد توصیه می‌شود. کاربردهای عملی شامل سیستم‌های اعلان، فریم‌ورک‌های افزونه و پردازش داده‌های بلادرنگ است. منابع اضافی شامل مستندات رسمی مایکروسافت و پروژه‌های open-source می‌باشد.

🧠 دانش خود را بیازمایید

آماده شروع

Test Your Knowledge

Test your understanding of this topic with practical questions.

4
سوالات
🎯
70%
برای قبولی
♾️
زمان
🔄
تلاش‌ها

📝 دستورالعمل‌ها

  • هر سوال را با دقت بخوانید
  • بهترین پاسخ را برای هر سوال انتخاب کنید
  • می‌توانید آزمون را هر چند بار که می‌خواهید تکرار کنید
  • پیشرفت شما در بالا نمایش داده می‌شود