PDA

View Full Version : آموزش Delegate در #C



بابک زواری
یک شنبه 12 تیر 1384, 14:34 عصر
نویسنده : داریوش تصدیقی
می توان گفت که Delegate یکی از ویژگی های جذاب زبان برنامه نویسی سی شارپ بوده که امکانات بالقوه فوق العاده ای را به این زبان می افزاید.

Delegate چیست؟

در واقع Delegate کلاسی است که اشیاء ساخته شده از آن می توانند توابع ثبت شده (Register) در خود را به ترتیب اجرا نمایند!. صبر کنید!!، فرار نکنید!!!، می دانم که این تعریف کمی وحشت آور است ولی نگران نباشید تا پایان بحث، موضوع کاملا شیرین خواهد شد.

برای استفاده از Delegate چهار مرحله اصلی وجود دارد که در ذیل، هر مرحله با مثال مشخص خواهد شد:

مرحله اول:

در این مرحله اقدام به تعریف کلاس Delegate می کنیم:


public delegate void MyDelegate(int n);
معنی عبارت فوق این است که ما می خواهیم یک کلاس Delegate تعریف کنیم که اشیاء آن بتوانند توابعی را در داخل خود ثبت کنند که پارامتر ورودی آنها یک عدد صحیح (int n) بوده و پارامتر خروجی (void) نداشته باشند.

برای روشن شدن مطلب کلاسی به نام Employee و به شکل ذیل تعریف می نماییم:


public class Employee
{
public int Age;
public string FullName;

public Employee(string fullName, int age)
{
Age = age;
FullName = fullName;
}

public void DoIt(int n)
{
System.Console.WriteLine("I'm " + FullName + ", I did it " + n + " times .");
}
}
همانگونه که مشاهده می کنید، ما به طور عمدی در این کلاس تابعی تعریف کرده ایم (DoIt) که پارامترهای ورودی و خروجی آن با آنچه که در تعریف Delegate عنوان گردیده است، مطابقت داشته باشد.

مرحله دوم:

در این مرحله نسبت به ایجاد یک شیء از کلاس MyDelegate اقدام می کنیم:



MyDelegate DelegateInstance;

در این دستور، ما یک شیء به نام DelegateInstance از کلاس (MyDelegate) تعریف نموده ایم.
حال برای ادامه مسیر، از کلاس Employee یک شیء به نام oEmployee به شکل ذیل ایجاد می کنیم:


Employee oEmployee = new Employee("Dariush Tasdighi", 33);
مرحله سوم:

در این مرحله تنها کافی است که تابع (متد) DoIt شیء oEmployee را در شیء DelegateInstance به شکلی که در ذیل ذکر گردیده است ثبت نماییم:


DelegateInstance = new MyDelegate(oEmployee.DoIt);
و اما مرحله چهارم (مرحله آخر):

در این مرحله با صدا زدن (Call) شیء DelegateInstance همراه با یک پارامتر عددی، تابع ثبت شده در داخل آن به همان پارامتر عددی مشخص شده اجرا می شوند. دقت کنید که در این مثال تنها یک تابع ثبت شده در داخل شیء Delegate وجود دارد.


DelegateInstance(5);
دست نگه دارید!، باور کنید که عقل خود را از دست نداده ایم!! کاملا واضح است که به راحتی می توانستیم پس از ایجاد شی، oEmployee، با اجرا کردن تابع Doit همراه با همان پارامتر عددی، به همان نتیجه نائل آییم. ولی دقت کنید که همیشه این چهار مرحله به این شکلی که در اینجا مطرح گردیده است در کنار هم قرار نمی گیرند. نکته جالبی که در این فنآوری وجود دارد این است که در یک پروژه واقعی، این چهار مرحله، هر کدام در یک قسمت از برنامه تعریف و بکارگرفته می شوند و این مساله امکانات بسیار مفید و جذابی را برای زبان برنامه نویسی سی شارپ به ارمغان می آورد






آموزش Delegate قسمت دوم

نگارش 1

همانگونه که در قسمت اول آموزش Delegate مشاهده کردید، ما تابعی از یک شیء را در داخل یک شیء Delegate ثبت (Register) نمودیم. حال در این قسمت تصمیم داریم توابع مربوط به چندین شیء را در داخل شیء Delegate ثبت نماییم تا در صورت صدا زدن (Call) شیء Delegate تمامی توابع ثبت شده در داخل آن به ترتیب اجرا شوند. برای این منظور به مثال ذیل توجه نمایید:



Employee oEmployee1 = new Employee("Ali Reza Alavi", 12);
Employee oEmployee2 = new Employee("Mohammad Ahmadi", 22);
Employee oEmployee3 = new Employee("Dariush Tasdighi", 32);

DelegateInstance = new MyDelegate(oEmployee1.DoIt);
DelegateInstance += new MyDelegate(oEmployee2.DoIt);
DelegateInstance += new MyDelegate(oEmployee3.DoIt);

در این مثال، ما سه شیء از کلاس Employee ایجاد کرده و به ترتیب توابع DoIt آنها را در داخل شیء Delegate ثبت کردیم. حال در صورتیکه شیء Delegate را با پارامتر 4 اجرا نماییم، تمامی توابع این سه شیء به ترتیب اجرا می شوند:


DelegateInstance(4);
چهار نکته اساسی:

نکته اول: توجه داشته باشید که هیچ لزومی ندارد شما توابع اشیاء یک کلاس خاص را در داخل یک شیء Delegate ثبت نمایید. شما می توانید توابع مربوط به اشیائی که از کلاس های مختلفی ایجاد شده اند را نیز تنها به شرط اینکه پارامترهای ورودی و خروجی آنها یکسان باشند در داخل شیء Delegate تبت نمایید.

نکته دوم: دقت کنید که برای ثبت اولین تابع درداخل یک شیء Delegate، باید از عملگر = (مساوی) استفاده کنید. در صورتیکه بخواهید توابع دیگری را نیز در داخل همان شیء Delegate ثبت نمایید، باید از عملگر =+ (بعلاوه مساوی) برای این منظور استفاده نمایید. لازم به ذکر است که اگر در این حالت، سهوا به جای استفاده از عملگر =+ از عملگر = استفاده کنید، تمامی توابع از قبل ثبت شده در داخل شیء Delegate به طور خودکار Unregistered می گردند!

نکته سوم: در صورتیکه تابعی از یک شیء (oEmployee2) را در داخل یک شیء Delegate ثبت کرده اید و بخواهید که شیء مذکور (oEmployee2) را از بین ببرید، ابتدا باید تابع مربوطه را با استفاده از عملگر =- (منها مساوی) Unregistered نموده و سپس نسبت به از بین بردن آن شیء اقدام نمایید:




DelegateInstance -= new MyDelegate(oEmployee2.DoIt);
oEmployee2 = null;

نکته چهارم: سوء تفاهم نشود! هر چند که در تمامی مثالهایی که تاکنون عنوان کردیم، تنها نسبت به ثبت توابع اشیاء در داخل شیء Delegate اقدام نمودیم، ولی دقت کنید که شما قادر به ثبت توابع استاتیک (Static) کلاس ها نیز در داخل اشیاء Delegate خواهید بود و همانطور که بارها نیز عنوان کردیم تنها شرط آن این است که پارامترهای ورودی و خروجی این توابع استاتیک نیز با ساختار کلاس Delegate مطابقت داشته باشند.

زنگ تفریح!:

خوب دوستان، با یک تمرین برای دست گرمی چطورین؟ حل این تمرین نه تنها تا حدی فلسفه استفاده از Delegate را مشخص می کند، بلکه مصداقی واقعی از بکارگیری Delegate در پروژه های واقعی خواهد بود:

تصور کنید کلاس عمومی در پروژه خود تعریف کرده اید که در داخل آن تابع استاتیکی با نام SendEmail تعبیه شده است. در جای دیگری در برنامه خود کلاس عمومی دیگری نیز برای چاپ اطلاعات در نظر گرفته اید و در آن تابعی با عنوان Print تعریف کرده اید. در این میان کلاس دیگری نیز وجود دارد که اشیاء آن وظیفه ثبت اطلاعات در بانک اطلاعاتی را با استفاده از تابعی به نام Save بر عهده دارند. تعریف این سه تابع نیز به گونه ای است که پارامترهای ورودی و خروجی آنها یکسان می باشند. حال تصور کنید که می خواهیم یک کلاس Delegate ایجاد و شیئی از آن تعریف نماییم. سپس این سه تابع را به ترتیب دلخواه در شیء Delegate مربوطه ثبت نماییم. دوستان عزیز، حال یکی از زیبایی های Delegate را در این تمرین تجربه خواهید کرد. با صدا زدن شیء Delegate همراه با پارامترهای مناسب، به طور خودکار متن مورد نظر در بانک اطلاعاتی ثبت و از طریق چاپگر چاپ و نامه الکترونیکی در رابطه با این عملیات برای مدیر سیستم ارسال می گردد!. بسیار خرسند خواهم شد که این برنامه ساده را نوشته و برای اینجانب ارسال نمایید.

به امید خداوند متعال در ادامه این آموزش، با مثالهای جذاب و پیچیده تری آشنا خواهید شد، پس با ما همراه باشید

Babak-Aghili
یک شنبه 12 تیر 1384, 15:48 عصر
http://weblog.iranasp.net/dariushtasdighi/archive/2005/04/16/1140.aspx

http://weblog.iranasp.net/dariushtasdighi/archive/2005/04/26/1264.aspx

COMPLETE CopyRight Low

:موفق:

dot_net_lover2
دوشنبه 13 تیر 1384, 18:30 عصر
اینم واسه اونایی که دوست دارن با RSS بحث اقای داریوش تصدیقی را دنبال کنند.
http://weblog.iranasp.net/dariushtasdighi/Rss.aspx
:موفق:

بابک زواری
سه شنبه 14 تیر 1384, 01:12 صبح
خوب بابا شما که این لینکها رو دارید چرا زودتر آستین بالا نمیزنید
حالا اگر چیز دیگه ایی در این زمینه دارید بسم الله :flower:

h.derakhshanfar
سه شنبه 05 مهر 1390, 21:05 عصر
با تشکر بسیار از آقای بابک زواری..اگه لطف کنید مثال های دیگری هم بزنید ممنون میشم.یه سئوال داشتم خدمتتون.من با tread میخواستم کار کنم..هنگامی که به یک کنترل میخواهم دسترسی داشته باشم خطای crooss tread میگیرم.جستجو کردم گفتن با delegate و invoke باید کار کرد.اگه توضیح بدید ممنون میشمومن اصلا نمیدونم invoke چی هست.با تشکر بسیار..

Babak-Magic
سه شنبه 05 مهر 1390, 21:38 عصر
البته اون خطا رو میشه اینجوری از سر بازش کرد با این کد
Form1.CheckForIllegalCrossThreadCalls = true;
ولی این روش درستی نیست روش درست همون استفاده از Delegate هست
من اینجا یک نمونه با استفاده از Thread و Delegate گذاشتم ببینش
http://projectiran.ir/Post.aspx?id=0

h.derakhshanfar
چهارشنبه 06 مهر 1390, 14:06 عصر
با تشکر اقای بابک.لطفا ی توضیح میدید Form1.CheckForIllegalCrossThreadCalls = tru دقیقا چ کار میکنه و کار دستور invoke چی هست؟اگه توضیح بدین ممنون میشم چون من ی برنامه نوشتم که متاسفانه هنگام کوئری گرفتن هنگ میکنه..خیلی لطف میکنید اگه یکم رو دستوراتون مخصوصا اینکه invoke چی هست و چ کار میکنه توضیح بدید و این برنامه ک نوشتید چ کار میکنه...خدا عمرتون بده

elyass-pc
سه شنبه 31 اردیبهشت 1392, 17:16 عصر
سلام
از دوستان کسی هست که این مباحث برام توضیح بده؟
Action<T> and Func<T> Delegates

uthman
سه شنبه 11 تیر 1392, 18:03 عصر
سلام آقا بابک.واقعا دستت درد نکنه خیلی عالی توضیح دادی.خیلی مطالب رو تو اینترنت و کتاب خودم ولی به اندازه شما خوب نگفته بودن.لطفا اگه میتونید ادامه بدید.راستی اگه وقت داشتید invok وevent رو هم بگید.منتظر شما هستیم.