تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
[نقاش] الـ Delegate
#1
السلام عليكم ورحمة الله وبركاته




سنتكلم في هذا المقال عن موضوع شيق ومفيد جدا وهو موضوع الـ 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 senderEventArgs e)
 
       {
 
           MyDelegate method GetSiteURL;
 
       


كود كامل :-
PHP كود :
       //delegate
 
       public delegate string MyDelegate(string arg1);


 
       private void Form1_Load(object senderEventArgs 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 senderEventArgs 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 senderEventArgs 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 senderEventArgs e)
 
       {
 
           MyDelegate method GetSiteURL;

//تمرير المفوض الى كلاس اخر
 
           Sites sites = new Sites();
 
           sites.PrintSites(method);
 
       





والان في الكلاس الاخر ، يوجد الكود التالي الذي سيقوم باستدعاء الدالة الموجودة في الكلاس الاصلي من خلال الDelegate Smile :
PHP كود :
   class Sites
    
{

 
       public void PrintSites(Form1.MyDelegate siteMethod)
 
       {
 
           //استدعاء الدالة التي يؤشر اليها المفوض
 
           siteMethod("com"); 
 
       }
 
   



هل رأيتم ذلك ؟ الكلاس Sites قام باستدعاء دالة موجودة في Class اخر بكل سهولة ودون تعريف Instance للكلاس الاصلي .




--


اذن استفدنا من الـ Delegate في:
  • "تأخير" استدعاء الدالة .
  • استدعاء دالة من مكان اخر باستعمال متغير يشير اليها .

الفكرتين فوق هما الاساس لمفهوم الـ Event حيث لو طورنا المثال السابق قليلا ليصبح بالشكل الموجود تحت ، سنفهم لماذا مفهوم الـ Event يعتمد على الـ Delegate .. بل اصلا الـ Event هو شكل من اشكال الـ DelegateSmile



PHP كود :
   public partial class Form1 Form
    
{
 
       //delegate
 
       public delegate void MyDelegate();

 
       private void Form1_Load(object senderEventArgs 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 099999999i++)
 
           {
 
               //some long job here
 
           }

 
           //الاكواد اعلاه ستاخذ وقت ليثما تكمل عملها ، وعندما تكمل عملها
 
           //سيتم استدعاء دالة موجودة في كلاس اخر بواسطة المفوض
 
           finishedMethod(); 
 
       }
 
   


صورة :-










الخاتمة


ان الـ Delegate احد المواضيع المهمة في البرمجة كائنية التوجه ، بل ويزيد الاهتمام فيه يوما بعد يوم خاصة بعد ظهور ميزات مثل  Anonymous method وLambda expression ، وبالخصوص ميزة الـ Anonymous method (دالة بدون اسم) حيث بما انها دالة بدون اسم ، فليس بالامكان استدعائها بالطريقة الاعتيادية !! فلا يمكن ابدا استدعائها الا بواسطة الـ Delegate Smile



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



تحياتي لكم
الرد }}}
#2
ما شاء الله عليك اخي الشاكي مبدع و تختار العناوين الحساسة 

هذه المواضيع وجب شرحها بافاضة لانها اللب و الاساس في الاعمال الاحترافية
ربما يكون لي وقفة مع Anonymous method,Anonymous Class,Anonymous Objects
تحياتي لك   Cool
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
الرد }}}
#3
(30-06-16, 04:32 AM)ابو ليلى كتب : ما شاء الله عليك اخي الشاكي مبدع و تختار العناوين الحساسة 

هذه المواضيع وجب شرحها بافاضة لانها اللب و الاساس في الاعمال الاحترافية
ربما يكون لي وقفة مع Anonymous method,Anonymous Class,Anonymous Objects
تحياتي لك   Cool


فعلا ما اتمناه هو ان المبرمج العربي يرتقي باسلوبه في البرمجة ويستعمل ميزات لغة البرمجة باحترافية

لان موضوع الـ clean code مهم جدا وللاسف الكثير لايعرفون ادارة مشاريعهم بطريقة صحيحة وبالتالي المصير هو الفشل في بعض الاحيان او يتعب كثير عشان يخلص مشروعه


لذلك دائما المح الى استخدام Design Pattern و معمارية محددة مثل N-tire او MVC في بناء المشاريع ، ولكن قبل الدخول في شرح هذه المواضيع العملاقة يجب على المبرمج العربي الالمام بجميع هذه المفاهيم مثل الDelegate والInterface وغيرههم

وماشاء الله عليك انت كذلك مبدع في ايصال هذه المعلومات Smile..
الرد }}}
تم الشكر بواسطة: ابو ليلى , Sajad , الوادي , Amir_Alzubidy
#4
اخي الشاكي دائما الجواب ياتي على حسب جنس السؤال و على حسب جنس القارئ
لب الفكرة يكمن في انك لو استخدمت الطرق الاحترافية في اجاباتك فان الاجابة لن تصل الى شخص او شخصين .
الاغلب اعتاد العمل بالطريقة الكلاسيكية و البسيطة و مرد ذلك للكثير من الاسباب اولها و على رأسها قلة المصادر العربية في هذه المجالات .
و ثانيها كسلنا المعتاد في تعلم هذه التقنيات من مصادرها الاساسية(المصادر الاجنبية) , اذ يقف بوجهك الكثير من العوائق اولها اللغة.
اما فيما يتعلق بشرح هذه التقنيات من قبل من يفهممها , ايضا هناك عوائق اولها الفراغ و ثانيها الاستعدادية و اخرها و اهمها قدرة الشارح على ايصال المعلومة بشكل مبسط و مفهوم لاكبر كم من القارئين.
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
الرد }}}
#5
يظهر راح أطالب الادارة بفتح قسم خاص باسم (لقاء العمالقة) سرقت الاسم من أمير ابن أمير  Big Grin
الرد }}}
#6
في كثير من الاحيان اقول لماذا لا نبحث عن مركز تكنولوجي او جهة رسمية تتبنى منتدانا ونشاطات اعضاءه المتميزين في حقيقة الامر ارى بمنتدانا حاضنة للابداع والمبدعين وسياستها في استقطاب العقول
لكن يجب علينا تمكين هذه النشاطات على المستوى الفردي اولا وعلى المستوى العالمي ثانيا . ليكون المرجع الاول لكل المبرمجين وتوضيف هذه العقول والاستفادة منها بشكل يليق بها اكثر .
شكرا جزيلا لكم واتمنى لكم التوفيق والنجاح
الرد }}}
#7
جميل اخ الشاكي و سلمت يداك ، اتمنى انزال مثل هذي المواضيع بشكل دوري
اسم معرفي : محمد يحيى
الرد }}}
تم الشكر بواسطة: الوادي , الشاكي لله , ابو ليلى
#8
حاولت ان ابسط الشرح بقدر الامكان ليناسب المبتدئين في هذه الامور حيث ان الموضوع ليس سهلا على المبتدئين, و ليكون لدى المبتدئ تصور بسيط عن الموضوع على حسب ما استطعت (احيانا المقارنة و الترجمة تفقد المعنى المطلوب) و لكن لا مشكلة من تمهيد بسيط يصل لاغلب القارئين

في البداية بعض المعلومات البسيطة لتسهيل الشرح اكثر ما يمكن

Delegates  (الوكلاء) نعم افضل تسمية في نظري هي وكيل؟؟

الوكيل يشبه الى حد بعيد المؤشر المستخدم في (C,C++).

مثال من الواقع

لو فرضنا ان لدينا شركة بالاسم (A) .

ولدى الشركة (A) بعض المنتجات (براد,مكيف,غسالة) وهذه الشركة لديها خدمة تسويق المنتجات عبر(مندوب ,وكيل) مهما كان الاسم.

نظريا هذا الوكيل لديه كل المعلومات عن المنتجات(الاسم,السعر,الموديل...الخ).

فانت عندما تتعامل مع الوكيل فانك ستملك كل المعلومات عن المنتجات التي توكل بها .

لو اردنا نحول هذا المثال الى واقع برمجي فأننا سنقول لدينا كلاس ما (مقر الشركة).

وهذا الكلاس فيه مجموعة من الدوال (ملفات تعريفية بالمنتجات في مقر الشركة).

و كل دالة من هذه الدوال تعطيننا معلومة محددة عن المنتج  معلومات عن (السعر,الموديل,الكفالة...الخ) و ذلك بعد تمرير اسم المنتج للدالة .

اذا هذا يقودنا الى ان الوكيل قام باستدعاء الدوال عند سؤاله عن منتج ما (اذا هو لعب دور المؤشر على الدالة).

يثار هنا تساؤل لماذا كل هذا اللف و الدوران (لماذا لا استدعي الدالة بشكل مباشر و خلصنا)؟؟

اخي السائل هناك ما يعرف في الواقع البرمجي بنظام التغليف encapsulation  الفائدة منه كبيرة (ليس الحديث للكلام عنه).

حيث نقوم بمثالنا السابق بتغليف كل الدوال السابقة (المعلومات عن المنتجات) مع وكيل واحد Delegate  و بعدها يمكن للوكيل ان يجيب عن كل سؤال عند الطلب منه.

Delegate  يقوم بهذه المهمة اذ انه يشير الى هذه الدالة (او مجموعة من الدوال)؟؟

نعم يستطيع التعامل مع مجموعة من الدوال نشرحه لاحقا.

هناك نوعين من الوكلاء (على حسب راي الشركة)

-        Single-cast delegates .الاول يشير و يتكلف بدالة واحدة (مندوب عن البرادات)

-        Multi-cast delegates يشير و يتكلف باكثر من دالة .

هيكلية الوكيل delegates  (يذكرني بمندوب المبيعات) يجب ان تتوفر به شروط ليصبح وكيل

-        اسم الوكيل ( تخيل وكيل بدون اسم؟).

-        نوع المدخلات التي يقبلها الوكيل (البارمترات).

-        نوع المخرجات التي يعيدها الوكيل (اذ انه سيتكفل بدوال تعيد مخرجات).

-        الوكيل يعرف public  .
انظر لهذا التعريف 

PHP كود :
public delegate void TestDelegate(string message); 

كما ترى اسم الوكيل    TestDelegate

معرف كـ Public 
يقبل مدخلات من النوع String
يعيد النوع Void
و انظر الى الكلمة  Delegate  و هي ما تميزه على انه نائب عن الدالة التي تقبل المدخلات من النوع String
يتوجب عليك دائما تمهيد الوكيل قبل استخدامه انظر لذلك

PHP كود :
TestDelegate t = new TestDelegate(Display); 

التطبيق العملي:

سنعرض مثال بالكود و بعده الشرح


PHP كود :
using System;
public 
delegate void TestDelegate(string message); //تعريف الوكيل
class Test
{
 
 public static void Display(string message)
 
 {
 
   Console.WriteLine("The string entered is : " message);
 
 }
 
 static void Main()
 
 {
 
   TestDelegate t = new TestDelegate(Display); //تمهيد الوكيل للاستخدام مع الدالة
 
   Console.WriteLine("Please enter a string");
 
   string message Console.ReadLine();
 
   t(message); //استخدام الوكيل
 
   Console.ReadLine();
 
 }


اولا عرفنا الوكيل TestDelegate

ثم الدالة Display  التي سينوب عنها الوكيل (سيشير لها,يتكفل بها...الخ) تاخذ بارميتر نصي
في جزء التنفيذ مهدنا للوكيل و ارسلنا معه الدالة
طلبنا من المستخدم ان يكتب النص الذي يريد
و اخيرا جواب الوكيل (استدعاء الدالة من النائب عنها,الذي توكل بها).
في تشبيهنا الواقعي السابق سيكون على الوكيل ان يستقبل السؤال من الزبون كان يقول له براد مثلا, بعدها يقوم الوكيل باستدعاء محتويات الدالة الخاصة بالبراد و ماتحتويه و يعيد له المعلومات اللازمة .
 
ماذا لو احببت ان استخدم الوكيل ليكون نائبا عن اكثر من دالة ,نعم يمكنني ذلك و بكل بساطة انظر للمثال التالي:


PHP كود :
using System;
public 
delegate void TestDelegate();
class 
Test
{
 
 public static void Display1()
 
 {
 
   Console.WriteLine("This is the first method");
 
 }
 
 public static void Display2()
 
 {
 
   Console.WriteLine("This is the second method");
 
 }
 
 static void Main()
 
 {
 
   TestDelegate t1 = new TestDelegate(Display1);
 
   TestDelegate t2 = new TestDelegate(Display2);
 
   t1 t1 t2// استخدمنا عملية دمج
 
   t1(); //الاستدعاء
 
   Console.ReadLine();
 
 }


الامور واضحة اليس كذلك.

يتبع...
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
الرد }}}
تم الشكر بواسطة: الشاكي لله , Sajad
#9
Event = is shape from Delegate shapes
But when release both
Delegate and Event in same act for example Click like this
used webpage
PHP كود :
protected void Page_Load(object senderEventArgs e)
    {
        
Button1.Click +=  delegate {
            
Title Title "Hello";
            
Button1.Text "clicked";   
        };
       
    }

    protected 
void Button1_Click(object senderEventArgs e)
    {
        
Title "none";
    } 
You'll see Event comes before delegate
How, why I didn't know
سبحان الله والحمدلله ولا إله إلا الله والله أكبر
 اللهم اغْفِرْ لِلمؤمنين والمؤمنات والمسلمين والمسلمات الأحياء منهم والأموات
الرد }}}
تم الشكر بواسطة: الشاكي لله , الشاكي لله
#10
(22-08-16, 07:56 PM)أبو عمر كتب : Event = is shape from Delegate shapes
But when release both
Delegate and Event in same act for example Click like this
used webpage
PHP كود :
protected void Page_Load(object senderEventArgs e)
 
   {
 
       Button1.Click +=  delegate {
 
           Title Title "Hello";
 
           Button1.Text "clicked"  
        
};
 
      
    
}

 
   protected void Button1_Click(object senderEventArgs e)
 
   {
 
       Title "none";
 
   
You'll see Event comes before delegate
How, why I didn't know

الترجمة :-

الـ Event هو شكل من اشكال الـ Delegate
ولكن عندما نقوم بإطلاقهما معا في نفس الغرض (مثلا Click Button ) ..
سنجد ان الـ Event ينطلق قبل الـ Delegate !!

<كود من صفحة ويب> :

PHP كود :
protected void Page_Load(object senderEventArgs e)
 
   {
 
       Button1.Click +=  delegate {
 
           Title Title "Hello";
 
           Button1.Text "clicked"  
        
};
 
      
    
}

 
   protected void Button1_Click(object senderEventArgs e)
 
   {
 
       Title "none";
 
   


-ابو عمر يسأل بتعجب-  : لماذا لم اكن اعلم عن هذا الموضوع !؟ 


---


تعليق المترجم : انا ايضا لم اكن اعلم ذلك حتى اخبرتنا Big Grin هههههه
ولكن اعتقد ان الموضوع يتمحور حول الاسبقية في عملية الـ Assignment ...
Button1.Click += VbButton1_Click
Button1.Click += VbButtton2_Click

حيث اعتقد ان VbButton1_Click سينطلق اولا لانه تم اسناده اولا

وهذا ماحصل بالصفحة لان الButton1_Click تما اسناده في اكواد الـ Design التي تتنفذ قبل اكواد الـ code-behind التي تحتوي على كود الـ Assign تبع الـ Delegate

في النهاية ، انا لم اجرب ذلك ولكن هذا مااعتقده Big Grin

يعطيك العافية
الرد }}}
تم الشكر بواسطة: أبو عمر , أبو عمر


المواضيع المحتمل أن تكون متشابهة .
الموضوع : الكاتب الردود : المشاهدات : آخر رد
  [نقاش] نقاش حول تطبيق الفاتورة الإلكترونية فى السعودية المرحلة الثانية Zatca Integration AmrSobhy 2 1,598 26-01-23, 09:09 PM
آخر رد: AmrSobhy
  [نقاش] الفرق بين الـ Interface , Abstract Class , Base Class , Sealed Class الشاكي لله 16 23,290 03-07-16, 06:52 AM
آخر رد: الشاكي لله
  Delegate & Event Abu Ehab 4 3,059 19-09-15, 02:08 AM
آخر رد: الشاكي لله
  ExpressionTrees & Func & Delegate & Action Abu Ehab 4 3,191 25-07-15, 03:49 AM
آخر رد: sherif khalid

التنقل السريع :


يقوم بقرائة الموضوع: بالاضافة الى ( 1 ) ضيف كريم