30-06-16, 04:15 AM
السلام عليكم ورحمة الله وبركاته
سنتكلم في هذا المقال عن موضوع شيق ومفيد جدا وهو موضوع الـ Delegate او كما يطلق عليه "مفوض"
لن اتكلم عن الكثير من التفاصيل المتعلقة بالـ Delegate مثل الـ Anonymous Methods, Lambda Expression او الـ Events
لان هذا المقال سيركز فقط على مفهوم الـ Delegate وكيف تستفيد منه .
الـ Delegate
الـ Delegate هو احد المفاهيم التابعة لمبدأ Encapsulation في جميع لغات البرمجة كائنية التوجه (OOP) . وبشكل عام، الـ Delegate يعتبر Type شأنه شان الـ Types الاخرى مثل Integer, Double , String والخ...على سبيل المثال : عند عمل متغير من نوع string يمكننا بالطبع تخزين اي نص بداخله . الجميع يعرف هذا الموضوع.
فاذا كان متغير من String يقوم بتخزين النصوص ، اذن متغير من Delegate ماذا يخزن ؟
بكلمات بسيطة .... الـ Delegate يقوم بتخزين عنوان الـ Method .
Delegate is a Pointer of Method
نعم ، الـ Delegate هو مؤشر الى الدوال او (مايطلق عليها البعض Routines ).
تعريف Delegate
عندما يأتي الموضوع الى الـ Delegate يجب علينا اولا تعريفه في الـ Class Scope ..
صحيح انه في اغلب الاحيان انت لست مضطرا الى تعريف Delegate بسبب ان مكتبات الـ .NET توفر العديد من الـ Delegate الجاهزة اشهرهم: Func و Action و MethodInvoker و Predicate ويوجد غيرهم .
ولكن في بعض الاحيان ستكون بحاجة الى تعريف Delegate وهذا بالطبع سنقوم بشرحه بعد قليل ..
---
اولا : الـ Delegate يُعرف في الـ Class Scope
ثانيا : الـ Delegate يفضل تعريفه كـ Public
ثالثا : عند التعريف يجب تحديد نوع الMethod الذي سيقوم الDelegate بالاشارة اليه .
تخيل الدالة التالية :-
PHP كود :
string GetSiteURL(string endFregment)
{
return "Vb4arb." + endFregment;
}
عندما نريد تعريف Delegate يشير الى الدالة اعلاه فيجب علينا تعريفه كالتالي :
PHP كود :
public delegate string MyDelegate(string arg1);
ولقد اختصرت الشرح في صورة واحدة :-
كما نرى ، الDelegate يجب ان :
- يُرجع نفس نوع القيمة التي ترجعها الدالة التي سيشير اليها (موضع بالاسود)
- يحتوي على نفس عدد ونفس نوع البرامترات (موضح بالاحمر)
تخزين الدالة بالـ Delegate
بعدما عرفنا الـ Delegate في الجزء السابق ، يمكننا الان ان نقوم بتعريف متغير من هذا الDelegate وتخزين عنوان الدالة بداخله :-
PHP كود :
private void Form1_Load(object sender, EventArgs e)
{
MyDelegate method = GetSiteURL;
}
كود كامل :-
PHP كود :
//delegate
public delegate string MyDelegate(string arg1);
private void Form1_Load(object sender, EventArgs e)
{
MyDelegate method = GetSiteURL;
}
//function
string GetSiteURL(string endFregment)
{
return "Vb4arb." + endFregment;
}
الان تم تخزين عنوان دالة GetSiteURL في متغير اسمه Method .
علما بان الـ Delegate ليس محصورا لدالة معينة ، بل يمكنك اسستخدام الـ Delegate الذي قمت بعريفه لاي دالة اخرى تحتوي على نفس ال Return Type + نفس نوع وعدد البارمتارت :-
PHP كود :
//delegate
public delegate string MyDelegate(string arg1);
private void Form1_Load(object sender, EventArgs e)
{
MyDelegate method = GetSiteURL;
MyDelegate method2 = GetCompanyAddress
}
//function
string GetSiteURL(string endFregment)
{
return "Vb4arb." + endFregment;
}
string GetCompanyAddress(string companyName)
{
return "Usa 23.3" + companyName;
}
كيف استفيد من Delegate
الان بعدما قمنا بعمل متغير يشير الى دالة معينة . نستطيع الان استدعاء تلك الدالة متى اردنا بواسطة المتغير..
اذن كيف استطيع استدعاء الدالة بواسطة متغير Delegate ؟
الموضوع يتم بكل بساطة على النحو التالي :-
PHP كود :
private void Form1_Load(object sender, EventArgs e)
{
MyDelegate method = GetSiteURL;
//استدعاء الدالة التي يؤشر اليها المفوض مع ارسال بارمتار لها
method("com");
}
وهذا الموضوع مفيد ، فيمكننا تمرير هذا المتغير الى classes اخرى :
انظر هذا الكلاس :-
PHP كود :
class Sites
{
public void PrintSites(Form1.MyDelegate siteMethod)
{
siteMethod("com");
}
}
الان يمكنننا تمرير متغير الDelegate الى الـ Class اعلاه بواسطة هذا الكود :-
PHP كود :
private void Form1_Load(object sender, EventArgs e)
{
MyDelegate method = GetSiteURL;
//تمرير المفوض الى كلاس اخر
Sites sites = new Sites();
sites.PrintSites(method);
}
والان في الكلاس الاخر ، يوجد الكود التالي الذي سيقوم باستدعاء الدالة الموجودة في الكلاس الاصلي من خلال الDelegate
:PHP كود :
class Sites
{
public void PrintSites(Form1.MyDelegate siteMethod)
{
//استدعاء الدالة التي يؤشر اليها المفوض
siteMethod("com");
}
}
هل رأيتم ذلك ؟ الكلاس Sites قام باستدعاء دالة موجودة في Class اخر بكل سهولة ودون تعريف Instance للكلاس الاصلي .
--
اذن استفدنا من الـ Delegate في:
- "تأخير" استدعاء الدالة .
- استدعاء دالة من مكان اخر باستعمال متغير يشير اليها .

PHP كود :
public partial class Form1 : Form
{
//delegate
public delegate void MyDelegate();
private void Form1_Load(object sender, EventArgs e)
{
MyDelegate method = Finished;
Jobs job = new Jobs();
job.DoJob(method);
}
//function
void Finished()
{
MessageBox.Show("Job is Completed");
}
}
class Jobs
{
public void DoJob(Form1.MyDelegate finishedMethod)
{
for (int i = 0; i < 99999999; i++)
{
//some long job here
}
//الاكواد اعلاه ستاخذ وقت ليثما تكمل عملها ، وعندما تكمل عملها
//سيتم استدعاء دالة موجودة في كلاس اخر بواسطة المفوض
finishedMethod();
}
}
صورة :-
الخاتمة
ان الـ Delegate احد المواضيع المهمة في البرمجة كائنية التوجه ، بل ويزيد الاهتمام فيه يوما بعد يوم خاصة بعد ظهور ميزات مثل Anonymous method وLambda expression ، وبالخصوص ميزة الـ Anonymous method (دالة بدون اسم) حيث بما انها دالة بدون اسم ، فليس بالامكان استدعائها بالطريقة الاعتيادية !! فلا يمكن ابدا استدعائها الا بواسطة الـ Delegate

الى هنا اتوقف ، واترك المايكروفون الى الاخوان اذا عندهم اي مداخلات او معلومات يحبون مشاركتها .
تحياتي لكم

