حسین احمدی
بنیانگذار توسینسو و برنامه نویس و توسعه دهنده ارشد وب

آموزش کار با Delegate ها در سی شارپ

در این آموزش قصد دارم تا خدمت شما دوستان مبحث Delegate ها در زبان سی شارپ رو توضیح بدم.  delegate ها، در حقیقت data type هایی هستند که می توانند یک متد را داخل خود ذخیره کنند. برای مثال، زمانی که شما متغیری از نوع int تعریف کردید، می توانید مقداری از نوع int در آن قرار دهید، delegate ها دقیقاً همین کار را برای متدها انجام می دهند.

دوره های شبکه، برنامه نویسی، مجازی سازی، امنیت، نفوذ و ... با برترین های ایران
سرفصل های این مطلب
  1. Multicast Delegate

برای یادگیری و آموزش سی شارپ ( آموزش زبان برنامه نویسی سی شارپ ) رایگان به این لینک بروید

دوستانی که با زبان سی پلاس پلاس کار کرده باشند، با مبحث Function Pointers آشنا هستند، Function Pointers دقیقاً معادل مفهوم delegate ها در زبان سی شارپ هستند که در این آموزش قصد داریم با آن ها آشنا شویم. هر data type ای در زبان سی شارپ باید تعریف شود، مانند کلاس ها که به ما اجازه تعریف Reference Type ها را می دهند یا struct ها که می توان با کمک آن ها Value Type ها را تعریف کرد. ساختار کلی تعریف delegate به صورت زیر است:

{access-modifier} delegate {return-type} {name}([parameters]);
  1. access-modifier: سطح دسترسی به delegate را مشخص می کند
  2. delegate: کلمه کلیدی که برای تعریف delegate ها استفاده می شود
  3. return-type: نوع داده بازگشتی را مشخص می کند که می تواند یکی از data type های تعریف شده باشد
  4. name: نام delegate را مشخص می کند
  5. parameters: پارامتر های ورودی را مشخص می کند

در حقیقت، زمان تعریف delegate ها، ما signature متدی که می توان در این delegate قرار داد را مشخص می کنیم. برای مثال، در کد زیر delegate ای با نام MethodPointer تعریف شده که می توان متدی با نوع بازگشتی int و دو پارامتر ورودی از نوع int در آن قرار داد:

public delegate int MethodPointer(int number1, int number2);

اما نحوه استفاده از این delegate چگونه است؟ فرض کنید متدی با نام Sum به صورت زیر تعریف کرده ایم:

static void Main(string[] args)
{            
}

public static int Sum(int number1, int number2)
{
    return number1 + number2;
}

حال برای استفاده از delegate تعریف شده می توان به صورت زیر عمل کرد:

static void Main(string[] args)
{
    MethodPointer pointer = Sum;
    Console.WriteLine(pointer(2, 5));
    Console.ReadKey();
}

همانطوری که مشاهده می کنید متغیری از نوع MethodPointer تعریف کردیم و داخل آن متد Sum را قرار دادیم و توانستیم متغیر مربوطه را فراخوانی کنیم. همیشه به این نکته توجه داشته باشید، زمانی که قصد دارید متدی را داخل یک delegate قرار دهید، می بایست signature متد و delegate یکسان باشد. با یک مثال موضوع را ادامه می دهیم، فرض کنید کلاسی داریم که عملیات مرتب سازی آرایه ای را برای ما انجام می دهد، ما می خواهیم نحوه مرتبط سازی، یعنی صعودی یا نزولی را بوسیله delegate ها به کلاس مربوطه پاس دهیم، برای اینکار ابتدا یک delegate تعریف می کنیم که می تواند متدی که عملیات مقایسه را برای ما انجام می دهد در خود نگه داری می کند:

public delegate bool SortStrategy(int number1, int number2);

در قدم بعدی کلاسی تعریف می کنیم که عملیات مرتبط سازی را برای ما انجام می دهد، اما الگوریتم مرتبط سازی را بوسیله پارامتری از نوع delegate تعریف شده به آن پاس می دهیم:

public class SortList
{
    public int[] Sort(int[] array, SortStrategy sortStrategy)
    {
        for (int x = 0; x < array.Length; x++)
        {
            for (int y = x; y < array.Length; y++)
            {
                if (sortStrategy(array[x], array[y]))
                {
                    int temp = array[x];
                    array[x] = array[y];
                    array[y] = temp;
                }
            }
        }
        return array;            
    }
}

برای استفاده از متد Sort در کلاس SortList، می بایست متدی که عملیات مقایسه بین خانه های آرایه را انجام می دهد، به عنوان ورودی دوم متد که از نوع delegate تعریف شده است را مشخص کنیم، پس ابتدا دو متد به صورت زیر تعریف می کنیم:

public static bool SortAscending(int number1, int number2)
{
    return number1 > number2;
}

public static bool SortDescending(int number1, int number2)
{
    return number1 < number2;
}

دقت کنید، متدهای تعریف شده signature ای مشابه delegate تعریف شده دارند. حال می توان به صورت زیر از کلاس SortList استفاده کرد:

int[] numbers = {2, 3, 6, 9, 7, 8, 5, 2, 3, 6, 9};

var sortList = new SortList();

foreach (var item in sortList.Sort(numbers,SortAscending))
{
    Console.WriteLine(item);
}

Console.ReadKey();

همانطور که مشاهده می کنید، زمان فراخوانی متد Sort، ابتدا آرایه مورد نظر برای مرتب سازی و سپس متد SortAscending را برای مرتب سازی صعودی لیست به عنوان پارامتر پاس داده شده است. برای مرتب سازی به صورت نزولی کافیست به جای متد SortAscending، متد SortDescending را به متد پاس دهیم.

Multicast Delegate

یکی از قابلیت های Delegate ها، توانایی نگهداری بیش از یک متد است، مانند آرایه ای که می توانند چندین مقدار را در خود نگه دارند. برای مثال، delegate زیر را تعریف می کنیم:

public delegate void MethodPointer(int number1, int number2);

کلاس Program را به صورت زیر تغییر می دهیم (کلاس Program کلاسی است که در تمامی برنامه ها وجود دارد و نقطه شروع برنامه ما است، مثال هایی که میزنیم در محیط Console است):

class Program
{
    static void Main(string[] args)
    {
        MethodPointer pointer = Sum;
        pointer += Substract;

        pointer(8, 3);

        Console.ReadKey();
    }

    public static void Sum(int number1, int number2)
    {
        Console.WriteLine(number1 + number2);
    }

    public static void Substract(int number1, int number2)
    {
        Console.WriteLine(number1 - number2);
    }
}

همانطوری که مشاهده می کنید، ابتدا متغیری از نوع MethodPointer، با نام pointer تعریف کردیم و متد Sum را داخل آن قرار دادیم. در خط بعدی بوسیله =+، متد Substract را به آن اضافه کردیم، با این کار متغیر pointer، آدرس دو متد Sum و Substract را نگهداری می کند و با فراخوانی آن هر دو متد برای ما اجرا شده و اعداد 11 و 5 در خروجی چاپ می شوند. امیدوارم که این آموزشی مورد توجه شما دوستان عزیز قرار گرفته باشد. در یک آموزش دیگر، در مورد Anonymous Method ها و Lambda Expression ها صحبت خواهیم کرد. 


حسین احمدی
حسین احمدی

بنیانگذار توسینسو و برنامه نویس و توسعه دهنده ارشد وب

حسین احمدی ، بنیانگذار TOSINSO ، توسعه دهنده وب و برنامه نویس ، بیش از 12 سال سابقه فعالیت حرفه ای در سطح کلان ، مشاور ، مدیر پروژه و مدرس نهادهای مالی و اعتباری ، تخصص در پلتفرم دات نت و زبان سی شارپ ، طراحی و توسعه وب ، امنیت نرم افزار ، تحلیل سیستم های اطلاعاتی و داده کاوی ...

نظرات