Знакомство с делегатами в C# (Часть 1)

Делегаты в C# (теория)

Доброго времени суток! В этой статье я хочу рассказать о том, что такое делегаты в C#, как их создавать и как ими пользоваться. Делегат — это сущность в программе, которая хранит ссылку на какой-либо метод, и при необходимости, может этот метод вызвать. Сразу же может возникнуть вопрос, а зачем вызывать метод через какого-то посредника, если можно вызвать его напрямую? Дело в том, что на этапе сборки программы, программист может не знать какой метод нужно будет вызвать в определенный момент выполнения программы. А использование делегатов, как раз позволяет написать, в какой-то степени, абстрактный код. Но об этом я расскажу в следующей статье, в которой покажу пример использования делегатов на практике. А пока просто поверьте мне на слово.

Ну давайте уже разберемся как создаются делегаты. Для создания делегата, нужно сначала определить его тип. Как и в случае классов, мы создаем некий шаблон, в соответствии с которым, буде в дальнейшем создавать конкретные экземпляры. Тип делегата определяется по следующему правилу:

delegate тип_значения ИмяТипаДелегата(список_параметров);

Как видите, объявление типа делегата, отчасти, похоже на объявление метода, но в самом начале, указывается ключевое слово delegate, а после списка аргументов, нет тела как у метода, вместо которого ставит символ «;».

Обратите внимание, объект-делегат может ссылаться только на такие методы, чья сигнатура (список параметров и тип возвращаемого значения, в данном контексте) полностью совпадает с объявлением типа этого делегата. Но ссылаться делегат может как на статические, так и на обычные методы классов.

Давайте рассмотрим на практике пример объявления типа делегата и создание конкретного экземпляра данного типа:

//Объявляем делегат, по сути - тип делегатов
delegate double DoubleDelegat(double aFirstArg, double aSecondArg);

//Основной класс программы
class Program
{
    //Статический метод, возвращающий сумму двух аргументов
    static double Sum(double aFirstSumArg, double aSecondSumArg)
    {
        return aFirstSumArg + aSecondSumArg;
    }

    //Главный метод программы (точка входа)
    static void Main(string[] args)
    {
        //Создаем экземпляр делегата DoubleDelegat (ссылающийся на метод Sum)
        DoubleDelegat sumDelegat = new DoubleDelegat(Sum);
    }
}

Как видите, создание делегата очень похоже на создание обычного объекта, но при создании объекта-делегата, мы указываем метод, на который ссылается делегат. В данном случае, это метод «Sum». А вызвать это метод через созданный делегат можно так:

//Вызов метода Sum через делегат sumDelegat
double sumResult = sumDelegat(24.5, 21.4);

В примере выше, мы вызвали метод «Sum», через делегат «sumDelegat», с параметрами «24.5» и «21.4». А ниже представлен пример, в котором создаются два объекта-делегата типа «DoubleDelegat», причем один выполняет метод сложения аргументов, а второй вычитания, хотя оба имеют один тип (но ссылаются на разные методы):

//Объявляем делегат, по сути - тип делегатов
delegate double DoubleDelegat(double aFirstArg, double aSecondArg);

//Основной класс программы
class Program
{
    //Статический метод, возвращающий сумму двух аргументов
    static double Sum(double aFirstSumArg, double aSecondSumArg)
    {
        return aFirstSumArg + aSecondSumArg;
    }

    //Статический метод, возвращающий разность двух аргументов
    static double Sub(double aFirstSumArg, double aSecondSumArg)
    {
        return aFirstSumArg - aSecondSumArg;
    }

    //Главный метод программы (точка входа)
    static void Main(string[] args)
    {
        //Создаем экземпляр делегата DoubleDelegat (ссылающийся на метод Sum)
        DoubleDelegat sumDelegat = new DoubleDelegat(Sum);

        //Вызов метода Sum через делегат sumDelegat
        double sumResult = sumDelegat(24.5, 21.4);

        //Вывод результата в консоль
        Console.WriteLine("Результат работы sumResult с методом Sum: " + sumResult);

        //Создаем экземпляр делегата DoubleDelegat (ссылающийся на метод Sum)
        DoubleDelegat subDelegat = new DoubleDelegat(Sub);

        //Вызов метода Sum через делегат sumDelegat
        double subResult = subDelegat(24.5, 21.4);

        //Вывод результата в консоль
        Console.WriteLine("Результат работы subResult с методом Sub: " + subResult);
    }
}

Таким образом, можно сделать вывод, что при объявлении типа делегата, мы указываем только прототип методов, которые этот делегат может вызывать, а что эти методы будут делать, мы можем даже не догадываться! И то, как этот факт мы можем использовать на практике, я расскажу в следующей статье.

Продолжение следует…

Добавить комментарий