Delegates و Events در سی شارپ

Delegates

در این مقاله راجب Delegates و Events در سی شارپ صحبت خواهیم کرد. نوع Delegate نشان دهنده ی یک delegate  در سی شارپ است.

Delegates در سی شارپ برای فراخوانی متدها در زمان اجرا مورد استفاده قرار می گیرند.

Delegate در NET. می تواند یک singlecast delegate یا یک multicast delegate باشد.

این آموزش با کدهای نمونه نحوه ی نمونه گیری از یک delegate ، ارجاع به یک delegate ، و فراخوانی یک delegate را درسی شارپ و NET. بیان می کند.

Delegates و Events مفهومی اساسی و در عین حال پیچیده در .NET و زبان سی شارپ هستند.

این مقاله مفاهیم پایه ی delegate ها و event ها و نحوه ی بکارگیری آن ها در .NET و برنامه ی سی شارپ را بیان می کند.

Delegates

delegate یکی از انواع پایه در .NET است.

delegate یک کلاس است، که برای ایجاد و فراخوانی delegate ها در زمان اجرا مورد استفاده قرار می گیرد.

Delegates

delegate در سی شارپ مشابه یک اشاره گر تابع در C یا C++ است. یک نوع جدید شیء در سی شارپ است.

delegate نوعی بسیار خاص از شیء است، چراکه پیش تر کل شی برای تعریف داده های مشمول مورد استفاده قرار می گرفت اما delegate تنها حاوی جزئیات یک متد است.

نیاز به delegate

برنامه نویسان اغلب نیاز به ارسال یک متد به عنوان پارامتر متدهای دیگر دارند.

به این منظور، Delegates را ایجاد کرده و مورد استفاده قرار می دهیم.

delegate کلاسی است که یک امضای متد را کپسوله سازی می کند.

گرچه می تواند در هر محتوایی مورد استفاده قرار گیرد، اما اغلب به عنوان مبنا برای مدل event handling (مدیریت رویداد) درسی شارپ و .NET عمل می کند.

یک روش مناسب برای فهم Delegates ، در نظر گرفتن delegate به عنوان چیزی که نامی به یک امضای متد می دهد است.

مثال:

public delegate int DelegateMethod(int x, int y);  

هر متدی که منطبق با امضای delegate باشد، که شامل نوع بازگشتی و پارامترها است، می تواند به delegate تخصیص داده شود.

این کار تغییر فراخوانی متدها بصورت برنامه ای را ممکن می سازد و نیز کد جدید را به کلاس های موجود اضافه می کند.

تا زمانی که امضای delegate را بدانید، می توانید متد خود delegate شده تان را تخصیص دهید.

این امکان، اشاره به یک متد به عنوان یک پارامتر، Delegates را برای تعریف متدهای بازفراخوانی/فراخوانی بازگشتی ایده آل می سازد.

جادوی delegate

در کلاس، شیء آن را ، که نمونه است، ایجاد میکنیم، اما در delegate هنگامی که نمونه ای ایجاد می کنیم نیز به آن delegate گفته می شود (بدین معنا که هرکاری که می کنید، delegate خواهد گرفت).

delegate در رابطه با کلاس شیئی که به آن اشاره دارد اطلاعی ندارد یا اهمیت نمی دهد.

هر شیء اینگونه خواهد بود؛ تنها مسئله ی مهم این است که انواع آرگومان های متد و نوع بازگشتی منطبق با delegate باشند.

این عامل، delegate ها را برای فراخوانی ” ناشناس” بسیار مناسب می سازد.

فواید delegate ها

به زبان ساده، delegate ها شی گرا و type safe (بدین معنا که انواع داده ای هنگام کامپایل شدن توسط کامپایلر بررسی و اعتبارسنجی می شوند) و بسیار ایمن هستند چراکه اطمینان حاصل می کنند که امضای متدی که فراخوانی می شود صحیح باشد.

delegate ها مدیریت رویدادها را ساده و آسان می سازند.

انواع delegate ها

دو نوع delegate وجود دارد، delegate های singlecast ، و delegate های multicast.

Singlecast delegate :

singlecast delegate به یک متد تکی در یک زمان اشاره دارد. در این حالت، delegate به یک متد تکی در یک زمان اختصاص می یابد.

این ها از کلاس System.Delegate مشتق می شوند.

Multicast delegate

هنگامی که یک delegate با بیش از یک متد بسته بندی می شود، به عنوان یک multicast delegate شناخته می شود.

در سی شارپ ، delegate های multicast هستند، بدین معنا که می توانند به بیش از یک تابع در یک زمان اشاره کنند.

این ها از کلاس System.MulticastDelegate مشتق می شوند.

تعریف و بکارگیری Delegates

سه مرحله در تعریف و بکارگیری delegate ها وجود دارد:

۱- تعریف

برای ایجاد یک delegate ، از کلیدواژه ی delegate استفاده می شود.

[attributes] [modifiers] delegate ReturnType Name ([formal-parameters]); 
  •  فاکتور/عامل خاصیت ها می تواند یک خاصیت نرمال سی شارپ باشد.
  • دسترسی میتواند یکی یا ترکیبی مناسب از کلیدواژه هایی که در ادامه می آیند باشد: new، public ، private ، protected، یا internal
  •  ReturnType (نوع بازگشتی) میتواند هر نوع داده ای که تا به حال استفاده کرده ایم باشد. همچنین می تواند یک نوع void (تهی) یا نام یک کلاس باشد.
  • Name باید یک نام معتبر سی شارپ باشد

از آنجایی که delegate تعریفی برای یک متد است، باید از پرانتزها ،که برای همه ی متدها مورد نیاز است، استفاده کنید.

اگر این متد هیچ آرگومانی نمی گیرد، پرانتزها را خالی بگذارید.

مثال:

public delegate void DelegateExample(); 

کد فوق نحوه ی تعریف یک delegate بدون پرانتز است.

۲- نمونه گیری

DelegateExample d1 = new DelegateExample(Display);  

کد فوق نحوه ی مقداردهی اولیه ی یک delegate را نشان می دهد.

۳- فراخوانی

d1();  

قطعه کد فوق delegate به نام d1() را فراخوانی می کند.

برنامه ای جهت نمایش Singlecast delegate

در اینجا یک کد نمونه که نحوه ی ایجاد و بکارگیری یک singlecast delegate را نمایش می دهد، آورده شده است.

using System;    
namespace ConsoleApplication5    
{    
class Program    
{    
public delegate void delmethod();    
  
public class P    
{  
  
public static void display()    
{    
Console.WriteLine("Hello!");    
}    
  
public static void show()    
{    
Console.WriteLine("Hi!");    
}    
  
public void print()
{
Console.WriteLine("Print");
}

}
  
static void Main(string[] args)
{
// here we have assigned static method show() of class P to delegate delmethod()
delmethod del1 = P.show;
  
// here we have assigned static method display() of class P to delegate delmethod() using new operator
// you can use both ways to assign the delagate
delmethod del2 = new delmethod(P.display);
P obj = new P();
  
// here first we have create instance of class P and assigned the method print() to the delegate i.e. delegate with class    
delmethod del3 = obj.print;
  
del1();
del2();
del3();
Console.ReadLine();
}
}
}

برنامه ای جهت نمایش Multicast delegate

در اینجا یک کد نمونه که نحوه ی ایجاد و بکارگیری یک multicast delegate را نمایش می دهد، آورده شده است.

using System;  
namespace delegate_Example4  
{  
  
class Program  
{  
public delegate void delmethod(int x, int y);  
  
public class TestMultipleDelegate  
{  
public void plus_Method1(int x, int y)  
{  
Console.Write("You are in plus_Method");  
Console.WriteLine(x + y);  
}  
  
public void subtract_Method2(int x, int y)  
{  
Console.Write("You are in subtract_Method");  
Console.WriteLine(x - y);  
}  
}  
  
static void Main(string[] args)  
{  
  
TestMultipleDelegate obj = new TestMultipleDelegate();  
delmethod del = new delmethod(obj.plus_Method1);  
  
// Here we have multicast  
del += new delmethod(obj.subtract_Method2);  
// plus_Method1 and subtract_Method2 are called  
del(50, 10);  
Console.WriteLine();  
//Here again we have multicast  
del -= new delmethod(obj.plus_Method1);  
//Only subtract_Method2 is called  
del(20, 10);  
Console.ReadLine();  
}  
}  
}  

نکاتی جهت به خاطر سپاری درباره ی Delegateها :

  • delegateها مشابه اشاره گرهای توابع C++ بوده، اما type safe هستند.
  •  delegate نامی به یک امضای متد می دهد.
  • delegate ها اجازه می دهند متدها به عنوان پارامتر ارسال شوند.
  •  delegate ها می توانند برای تعریف متدهای فراخوانی بازگشتی استفاده شوند.
  • delegate ها می توانند به یکدیگر زنجیر شوند؛ برای مثال، چندین متد می توانند در یک رویداد تکی فراخوانی شوند.
    سی شارپ نسخه ی ۲.۰ مفهوم Anonymous Methods (متدهای ناشناس) را ارائه می دهد، که ارسال بلوک های کد را به عنوان پارامترها به جای یک متد تعریف شده بصورت جداگانه مجاز می کند.
  •  delegate به بهینه سازی کد کمک می کند.
  • محل های استفاده از delegateها

رایج ترین مثال استفاده از delegate ها در رویدادها است.

  • بطور گسترده در نخ کشی (threading) استفاده می شوند.
  • delegate ها همچنین برای کتابخانه های کلاس generic ، که دارای تعریف عملکرد generic است، استفاده می شوند.

delegate های ناشناس

می توانید یک delegate ایجاد کنید، اما نیازی نیست متد مرتبط با آن را تعریف کنید.

نیازی نیست یک متد را بطور صریح پیش از استفاده از delegate تعریف کنید.

چنین متدی به نام ناشناس ( anonymous ) شناخته می شود.

به بیان دیگر، اگر خود delegate حاوی تعریف متد خودش باشد، با نام متد ناشناس شناخته می شود.

این کد مثالی از بکارگیری یک delegate ناشناس است.

using System;  
  
public delegate void Test();  
  
public class Program  
{  
static int Main()  
{  
Test Display = delegate()  
{  
Console.WriteLine("Anonymous Delegate method");  
};  
  
Display();  
return 0;  
}  
}

نکته: می توانید رویداد را در متد ناشناس نیز مدیریت کنید.

رویدادها

رویدادها و delegate با یکدیگر کار می کنند.

یک رویداد، ارجاعی به یک delegate است، یعنی هنگامیکه یک رویداد انجام می گیرد، یک delegate فراخوانی می شود.

به بیان سی شارپ، رویدادها صورتی خاص از delegate ها هستند.

رویدادها نقشی مهم در رابط های کاربری و اعلان های برنامه نویسی ایفا می کنند.

رویدادها و delegate ها دست به دست کار می کنند تا ارتباطی بین کد از یک کلاس به کلاس دیگر فراهم کنند.

هنگامیکه اتفاقی در یک کلاس یا یک بخش از کد رخ می دهد و بخش دیگر کد نیاز به یک اعلان دارد، از رویدادها استفاده می شود.

یک رویداد سی شارپ عضوی از یک کلاس است که هر زمان رویدادی که برای آن طراحی شده رخ دهد، فعال می شود.

با کلاسی شروع می شود که یک رویداد را تعریف می کند. هر کلاس، شامل همان کلاسی که رویداد در آن تعریف شده، یکی از متدهای خود را برای رویداد ثبت می کند.

این اتفاق از طریق یک delegate رخ می دهد، که امضای متدی که برای رویداد ثبت شده است را مشخص می کند.

کلیدواژه ی event یک دسترسی delegate است. همواره باید در ارتباط با یک delegate استفاده شود.

delegate ممکن است یکی از delegate های از پیش تعریف شده ی .NET باشد یا یکی که خودتان تعریف میکنید.

هر کدام که مناسب باشد، delegate را به رویداد تخصیص می دهید، که بطور مؤثر متدی که هنگام اجرای رویداد فراخوانی میشود را ثبت میکند.

چگونه از رویدادها در سی شارپ استفاده کنیم؟

هنگامیکه یک رویداد تعریف می شود، پیش از اینکه بتواند مورد استفاده قرار بگیرد، باید با یک یا چند مدیریت کننده ی رویداد (event handler) در ارتباط باشد.

یک مدیریت کننده ی رویداد چیزی جز یک متد که با استفاده از یک delegate فراخوانی می شود، نیست.

از عملگر += برای مرتبط کردن یک رویداد با نمونه ای از یک delegate که از پیش موجود است، استفاده کنید.

مثال:

obj.MyEvent += new MyDelegate(obj.Display);  

یک رویداد، در صورتیکه هیچ شنونده ی ثبت شده ای نداشته باشد، دارای مقدار null است.

گرچه رویدادها اغلب در برنامه نویسی کنترل های ویندوز استفاده می شوند، اما می توانند در کنسول، وب و دیگر برنامه ها نیز پیاده ساز ی شوند.

برنامه ای برای ایجاد یک Singlecast delegate و رویداد دلخواه

using System;  
namespace delegate_custom  
{  
class Program  
{  
public delegate void MyDelegate(int a);  
  
public class XX  
{  
public event MyDelegate MyEvent;  
  
public void RaiseEvent()  
{  
MyEvent(20);  
Console.WriteLine("Event Raised");  
}  
  
public void Display(int x)  
{  
Console.WriteLine("Display Method {0}", x);  
}  
}  
  
static void Main(string[] args)  
{  
  
XX obj = new XX();  
obj.MyEvent += new MyDelegate(obj.Display);  
  
obj.RaiseEvent();  
Console.ReadLine();  
}  
}  
} 

برنامه ای برای ایجاد یک Multicast delegate و رویداد دلخواه

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
  
namespace delegate_custom_multicast  
{  
class Program  
{  
public delegate void MyDelegate(int a, int b);  
  
public class XX  
{  
public event MyDelegate MyEvent;  
  
public void RaiseEvent(int a, int b)  
{  
MyEvent(a, b);  
Console.WriteLine("Event Raised");  
}  
  
public void Add(int x, int y)  
{  
Console.WriteLine("Add Method {0}", x + y);  
}  
  
public void Subtract(int x, int y)  
{  
Console.WriteLine("Subtract Method {0}", x - y);  
}  
}  
  
static void Main(string[] args)  
{  
  
XX obj = new XX();  
obj.MyEvent += new MyDelegate(obj.Add);  
obj.MyEvent += new MyDelegate(obj.Subtract);  
obj.RaiseEvent(20, 10);  
Console.ReadLine();  
}  
}  
}  

امیدوارم این مقاله شما را در درک delegate ها و event ها یاری کرده باشد.

زهره سلطانیان

نوشته‌های مرتبط

دیدگاه‌ها

*
*

این سایت از اکیسمت برای کاهش هرزنامه استفاده می کند. بیاموزید که چگونه اطلاعات دیدگاه های شما پردازش می‌شوند.