delegate (وکیل) چیست؟
شما می توانید فکر کنید یک delegate یک شیئ است که یک یا چند متد را در خود نگهداری می کند. البته درحالت نرمال، اشیائ خاصیت اجرایی ندارند، اما یک delegate با اشیاء معمولی تفاوت دارد. شما می توانید یک delegate را اجرا کنید و هنگامی که شما چنین کاری انجام دهید، آن delegate تمام متد یا متدهایی را که در خود نگهداری می کند را اجرا خواهد کرد.
دراین فصل املاء (syntax) و معناشناسی ساخت و استفاده از delegate را توضیح خواهیم داد. در فصول آینده خواهیم دید که چگونه می توانیم با استفاده از delegate ها کدهای اجرایی را از یک متد به متد دیگر پاس دهیم و اینکه چرا اینکار سودمند است.
ما با یک مثال شروع خواهیم کرد. اگر همه چیز کاملا" شفاف نیست، فعلا" نگران نباشید، چون جزئیات delegate را در ادامه فصل توضیح خواهیم داد.
- کد با اعلان یک نوع وکالتی بنام MyDel شروع می شود. (بله یک "نوع" وکالتی نه یک شیئ وکالتی)
- کلاس Program سه متد را اعلان می کند: PrintLow ، PrintHigh و Main. نوع وکالتی ساخته شده توسط ما، مختصرا" یکی از متدهای PrintLow یا PrintHigh را نگهداری خواهد کرد. اما اینکه کدامیک استفاده خواهد شد، تا زمان اجرای برنامه مشخص نیست.
- متد Main یک متغیر بنام del اعلان می کند که یک ارجاع به یک شیئ وکالتی از نوع MyDel را نگهداری می کند. این کار شیئ را نمی سازد. این فقط متغیری که قرار است ارجاع به شیئ وکالتی را نگهداری کند را می سازد؛ که در چندین خط پائین تر ساخته شده و مقداردهی می شود.
- خط بعد بررسی می کند که آیا عدد شانسی تولید شده از 50 کوچکتر است (دقت کنید که از عملگر شرطی سه بخشی برای برگرداندن وکیل مورد نظر استفاده کرده ایم).
- اگر مقدار کمتر از 50 باشد، شیئ وکالتی MyDel را ساخته و با ارجاع به متد PrintLow مقداردهی اولیه می کند.
- در غیر اینصورت شیئ وکالتی MyDel را که ارجاع به متد PrintHigh را نگهداری می کند را می سازد.
- در آخر متد Main شیئ وکالتی MyDel را اجرا می کند. (این شیئ ممکن است هر کدام از ارجاع های PrintLow یا PrintHigh را در خود نگهداری کند.)
delegate void MyDel(int value); // Declare delegate TYPE.
class Program
{
void PrintLow(int value)
{
Console.WriteLine("{0} - Low Value", value);
}
void PrintHigh(int value)
{
Console.WriteLine("{0} - High Value", value);
}
static void Main()
{
Program program = new Program();
MyDel del; // Declare delegate variable.
// Create random-integer-generator object and get a random
// number between 0 and 99.
Random rand = new Random();
int randomValue = rand.Next(99);
// Create a delegate object that contains either PrintLow or
// PrintHigh, and assign the object to the del variable.
del = randomValue < 50
? new MyDel(program.PrintLow)
: new MyDel(program.PrintHigh);
del(randomValue); // Execute the delegate.
}
}
چون ما از عدد شانسی استفاده می کنیم، نتیجه اجرای برنامه هربار تغییر می کند. در یکی از اجراها نتیجه زیر حاصل شد:
28 - Low Value
بررسی اجمالی delegate ها
حالا اجازه بدین کمی به جزئیات بپردازیم. یک delegate یک نوع-کاربرتعریف است، درست همونطوری که یک کلاس می تونه کاربرتعریف باشه (یعنی خود برنامه نویس اونو تعریف می کنه). اما درحالیکه یک کلاس نشاندهنده مجموعه از داده ها و متدهاست ، یک delegate از یک یا بیش از یک متد و مجموعه ای از اعمال از پیش تعریف شده نگهداری می کند.
شما با انجام مراحل زیر از یک delegate استفاده می کنید. من در قسمت های آینده هر یک از مراحل زیر رو با جزئیات توضیح خواهم داد.
- یک نوع وکالتی (delegate) را اعلان کنید. اعلان delegate مشابه اعلان متد است، با این تفاوت که وکیل دارای بلوک پیاده سازی نمی باشد.
- یک متغیر وکالتی از نوع همان وکیلی که ساخته بودید اعلان کنید.
- یک شیئ از نوع همان وکیل ساخته و متغیر وکالتی را به آن انتساب دهید. شیئ وکالتی جدید حاوی یک ارجاع به یک متد است که آن متد باید دارای امضا و نوع برگشتی مشابه نوع وکالتی تعریف شده در گام اول باشد.
- شما می توانید بطور اختیاری متدهای اضافی را به شیئ وکالتی اضافه کنید. این متد های باید حتما" دارای امضا و نوع برگشتی مشابه نوع وکالتی تعریف شده در گام اول باشند.
- در داخل کدنویسی خودتان می توانید وکیل را احضار کنید، درست همانطوری که یک متد را احضار می کنید. وقتی delegate را احضار می کنید، تک تک متدهایی که در داخل delegate وجود دارد اجرا می شوند.
با نگاه کردن به گام های قبل، متوجه خواهید شد که این مراحل شبیه مراحل ساختن کلاس هستند. شکل زیر مراحل ساختن و استفاده کردن کلاس ها و delegate ها را با هم مقایسه می کند.
شما می توانید یک delegate را بصورت یک شیئ که حاوی یک لیست مرتب شده از متدهاست تصور کنید. متدها دارای امضا و نوع برگشتی مشابه وکیل خود می باشند.
- به لیست متدها "لیست احضار (Invocation list)" می گویند.
- متدهای نگهداری شده توسط یک وکیل می توانند متعلق به هر کلاس یا ساختاری باشند، تا زمانی که با دو مورد زیر مطابقت داشته باشند:
- نوع برگشتی وکیل
- امضای وکیل (شامل اصلاحگرهای ref و out)
- متدهای موجود در لیست احضار می توانند متدهای نمونه یا متدهای استاتیک باشند.
- وقتی یک delegate احضار شود، تک تک متدهای موجود در لیست احضارش اجرا می شوند.