المشاركات : 1,733
المواضيع 147
الإنتساب : Sep 2012
السمعة :
215
الشكر: 8484
تم شكره 12163 مرات في 1145 مشاركات
30-06-16, 04:15 AM
(آخر تعديل لهذه المشاركة : 30-06-16, 05:41 AM {2} بواسطة الشاكي لله.)
السلام عليكم ورحمة الله وبركاته
سنتكلم في هذا المقال عن موضوع شيق ومفيد جدا وهو موضوع الـ 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 في:
- "تأخير" استدعاء الدالة .
- استدعاء دالة من مكان اخر باستعمال متغير يشير اليها .
الفكرتين فوق هما الاساس لمفهوم الـ Event حيث لو طورنا المثال السابق قليلا ليصبح بالشكل الموجود تحت ، سنفهم لماذا مفهوم الـ Event يعتمد على الـ Delegate .. بل اصلا الـ Event هو شكل من اشكال الـ 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
الى هنا اتوقف ، واترك المايكروفون الى الاخوان اذا عندهم اي مداخلات او معلومات يحبون مشاركتها .
تحياتي لكم
المشاركات : 662
المواضيع 39
الإنتساب : Feb 2014
السمعة :
195
الشكر: 1474
تم شكره 1740 مرات في 622 مشاركات
ما شاء الله عليك اخي الشاكي مبدع و تختار العناوين الحساسة
هذه المواضيع وجب شرحها بافاضة لانها اللب و الاساس في الاعمال الاحترافية
ربما يكون لي وقفة مع Anonymous method,Anonymous Class,Anonymous Objects
تحياتي لك
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
المشاركات : 1,733
المواضيع 147
الإنتساب : Sep 2012
السمعة :
215
الشكر: 8484
تم شكره 12163 مرات في 1145 مشاركات
30-06-16, 04:52 AM
(آخر تعديل لهذه المشاركة : 30-06-16, 05:02 AM {2} بواسطة الشاكي لله.)
(30-06-16, 04:32 AM)ابو ليلى كتب : ما شاء الله عليك اخي الشاكي مبدع و تختار العناوين الحساسة
هذه المواضيع وجب شرحها بافاضة لانها اللب و الاساس في الاعمال الاحترافية
ربما يكون لي وقفة مع Anonymous method,Anonymous Class,Anonymous Objects
تحياتي لك
فعلا ما اتمناه هو ان المبرمج العربي يرتقي باسلوبه في البرمجة ويستعمل ميزات لغة البرمجة باحترافية
لان موضوع الـ clean code مهم جدا وللاسف الكثير لايعرفون ادارة مشاريعهم بطريقة صحيحة وبالتالي المصير هو الفشل في بعض الاحيان او يتعب كثير عشان يخلص مشروعه
لذلك دائما المح الى استخدام Design Pattern و معمارية محددة مثل N-tire او MVC في بناء المشاريع ، ولكن قبل الدخول في شرح هذه المواضيع العملاقة يجب على المبرمج العربي الالمام بجميع هذه المفاهيم مثل الDelegate والInterface وغيرههم
وماشاء الله عليك انت كذلك مبدع في ايصال هذه المعلومات ..
المشاركات : 662
المواضيع 39
الإنتساب : Feb 2014
السمعة :
195
الشكر: 1474
تم شكره 1740 مرات في 622 مشاركات
اخي الشاكي دائما الجواب ياتي على حسب جنس السؤال و على حسب جنس القارئ
لب الفكرة يكمن في انك لو استخدمت الطرق الاحترافية في اجاباتك فان الاجابة لن تصل الى شخص او شخصين .
الاغلب اعتاد العمل بالطريقة الكلاسيكية و البسيطة و مرد ذلك للكثير من الاسباب اولها و على رأسها قلة المصادر العربية في هذه المجالات .
و ثانيها كسلنا المعتاد في تعلم هذه التقنيات من مصادرها الاساسية(المصادر الاجنبية) , اذ يقف بوجهك الكثير من العوائق اولها اللغة.
اما فيما يتعلق بشرح هذه التقنيات من قبل من يفهممها , ايضا هناك عوائق اولها الفراغ و ثانيها الاستعدادية و اخرها و اهمها قدرة الشارح على ايصال المعلومة بشكل مبسط و مفهوم لاكبر كم من القارئين.
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
المشاركات : 531
المواضيع 4
الإنتساب : May 2016
السمعة :
55
الشكر: 694
تم شكره 535 مرات في 367 مشاركات
يظهر راح أطالب الادارة بفتح قسم خاص باسم (لقاء العمالقة) سرقت الاسم من أمير ابن أمير
المشاركات : 2,470
المواضيع 3
الإنتساب : Nov 2014
السمعة :
602
الشكر: 17075
تم شكره 15268 مرات في 2999 مشاركات
في كثير من الاحيان اقول لماذا لا نبحث عن مركز تكنولوجي او جهة رسمية تتبنى منتدانا ونشاطات اعضاءه المتميزين في حقيقة الامر ارى بمنتدانا حاضنة للابداع والمبدعين وسياستها في استقطاب العقول
لكن يجب علينا تمكين هذه النشاطات على المستوى الفردي اولا وعلى المستوى العالمي ثانيا . ليكون المرجع الاول لكل المبرمجين وتوضيف هذه العقول والاستفادة منها بشكل يليق بها اكثر .
شكرا جزيلا لكم واتمنى لكم التوفيق والنجاح
المشاركات : 277
المواضيع 18
الإنتساب : Dec 2013
السمعة :
34
الشكر: 1057
تم شكره 2872 مرات في 215 مشاركات
جميل اخ الشاكي و سلمت يداك ، اتمنى انزال مثل هذي المواضيع بشكل دوري
اسم معرفي : محمد يحيى
المشاركات : 662
المواضيع 39
الإنتساب : Feb 2014
السمعة :
195
الشكر: 1474
تم شكره 1740 مرات في 622 مشاركات
04-07-16, 02:34 AM
(آخر تعديل لهذه المشاركة : 04-07-16, 02:45 AM {2} بواسطة ابو ليلى.)
حاولت ان ابسط الشرح بقدر الامكان ليناسب المبتدئين في هذه الامور حيث ان الموضوع ليس سهلا على المبتدئين, و ليكون لدى المبتدئ تصور بسيط عن الموضوع على حسب ما استطعت (احيانا المقارنة و الترجمة تفقد المعنى المطلوب) و لكن لا مشكلة من تمهيد بسيط يصل لاغلب القارئين
في البداية بعض المعلومات البسيطة لتسهيل الشرح اكثر ما يمكن
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(); } }
ا لامور واضحة اليس كذلك.
يتبع...
اللهم لك الحمد كما ينبغي لجلال وجهك و عظيم سلطانك
في حل و ترحال
المشاركات : 1,379
المواضيع 83
الإنتساب : Sep 2012
السمعة :
217
الشكر: 10451
تم شكره 17812 مرات في 844 مشاركات
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 sender, EventArgs e) { Button1.Click += delegate { Title = Title + "Hello"; Button1.Text = "clicked"; }; }
protected void Button1_Click(object sender, EventArgs e) { Title = "none"; }
You'll see Event comes before delegate
How, why I didn't know
سبحان الله والحمدلله ولا إله إلا الله والله أكبر
اللهم اغْفِرْ لِلمؤمنين والمؤمنات والمسلمين والمسلمات الأحياء منهم والأموات
المشاركات : 1,733
المواضيع 147
الإنتساب : Sep 2012
السمعة :
215
الشكر: 8484
تم شكره 12163 مرات في 1145 مشاركات
01-09-16, 01:44 AM
(آخر تعديل لهذه المشاركة : 01-09-16, 02:02 AM {2} بواسطة الشاكي لله.)
(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 sender, EventArgs e) { Button1.Click += delegate { Title = Title + "Hello"; Button1.Text = "clicked"; }; }
protected void Button1_Click(object sender, EventArgs 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 sender, EventArgs e) { Button1.Click += delegate { Title = Title + "Hello"; Button1.Text = "clicked"; }; }
protected void Button1_Click(object sender, EventArgs e) { Title = "none"; }
-ابو عمر يسأل بتعجب- : لماذا لم اكن اعلم عن هذا الموضوع !؟
---
تعليق المترجم : انا ايضا لم اكن اعلم ذلك حتى اخبرتنا هههههه
ولكن اعتقد ان الموضوع يتمحور حول الاسبقية في عملية الـ Assignment ...
Button1.Click += VbButton1_Click
Button1.Click += VbButtton2_Click
حيث اعتقد ان VbButton1_Click سينطلق اولا لانه تم اسناده اولا
وهذا ماحصل بالصفحة لان الButton1_Click تما اسناده في اكواد الـ Design التي تتنفذ قبل اكواد الـ code-behind التي تحتوي على كود الـ Assign تبع الـ Delegate
في النهاية ، انا لم اجرب ذلك ولكن هذا مااعتقده
يعطيك العافية
|