Делегаты в C#

Введение в делегаты.

Делегат в C# – это тип который содержит ссылку на какой-либо метод. Делегаты удобны тем, что их можно передать в метод в качестве параметра. В общем виде объявление типа делегата выглядит так:

модификаторДоступа delegate возвращаемоеЗначение ИмяТипаДелегата (параметры);

Создание экземпляра делегата:

ИмяТипаДелегата имяДелегата = new ИмяТипаДелегата( ИмяМетода );

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

Рассмотрим создание типа делегата и его экземпляров на примере.

using System;

class Program {
    // объявление типа делегата
    delegate void TestDelegateType();

    static void Main() {
        Console.ReadKey();
    }
}

В пятой строке кода объявляется делегат TestDelegateType. Тип его возвращаемого значения void, а количество параметров равно нулю. Добавим в этот пример один метод – TargetMethod, и создадим экземпляр делегата TestDelegateType.

using System;

class Program {
    // объявление типа делегата
    delegate void TestDelegateType();

    static void Main() {
        // создание экземпляра делегата TestDelegateType 
        TestDelegateType testDelegateInstance = new TestDelegateType( TargetMethod );
        // вызов метода из делегата
        testDelegateInstance();

        Console.ReadKey();
    }

    // Тестовый метод для передачи делегату TestDelegateType
    static void TargetMethod()
    {
        Console.WriteLine("Вызов из делегата.");
    }    
}

В 9-й строчке кода происходит создание экземпляра делегата TestDelegateType, в конструкторе ему передается метод TargetMethod, имеющий то же количество параметров и тот же тип возвращаемого значения, что и делегат TestDelegateType.

В 11-й строчке кода, происходит вызов делегата.

Пример использования делегатов.

Начинающие изучать C# часто долго не могут понять зачем нужны делегаты. Для того что бы понять смысл использования делегатов представим, что заказчик попросил разработать какой-то необычный элемент управления, например, кнопку, для использования в своих программах. Для этого мы разработаем класс, упакуем его в библиотеку и отправим заказчику. Когда пользователь нажимает на кнопку, должен выполняться код заказчика, на момент разработки кнопки, мы не знаем что это за код. Заказчик может создать несколько кнопок, как это часто бывает в формах, и каждая кнопка должна выполнять свой код. Для того, чтобы заказчик имел возможность передавать кнопке произвольные участки своего кода, для обработки нажатия кнопки, используем делегаты.

namespace DevControls {
    public class Button {
       // Объявляем тип делегата, обрабатывающего нажатия кнопки
       public delegate void ButtonClickHandler();
      
       // Экземпляр делегата, для обработки нажатий
       public ButtonClickHandler OnButtonClicked;

       // Этот метод будет имитировать нажатие кнопки
       public void Click() {
           if (OnButtonClicked != null)
               OnButtonClicked(); // Обработка нажатия
       }
   }
}

Мы создали тип делегата ButtonClickHandler, который определяет методы заказчика, пригодные для выполнения кнопкой. И определили открытый член класса OnButtonClicked, который имеет тип нашего делегата. Теперь заказчик может передать ему любой свой метод, подходящий под тип нашего делегата. Для проверки работы класса, мы создали метод Click(), который будет имитировать нажатие пользователем кнопки.

Теперь посмотрим как это будет работать на стороне клиента:

using DevControls; // включаем ссылку на библиотеку с кнопкой
using System;

namespace ClientSide {
    class Program {
        static void Main() {
            // создаем первую кнопку
            Button button1 = new Button();
            // создаем экземпляр делегата для 1 кнопки
            button1.OnButtonClicked = 
                new Button.ButtonClickHandler(Button1Clicked);
            button1.Click();

            // создаем вторую кнопку
            Button button2 = new Button();
            // создаем экземпляр делегата для 2 кнопки
            button2.OnButtonClicked = 
                new Button.ButtonClickHandler(Button2Clicked);
            button2.Click();

            Console.ReadKey();
        }

        // обработчик первой кнопки
        static void Button1Clicked() {
            Console.WriteLine("Button1 clicked!");
        }

        // обработчик второй кнопки
        static void Button2Clicked() {
            Console.WriteLine("Button2 clicked!");
        }
    }
}

Вывод тестового приложения:

Вывод тестового приложения

Событийная модель C# основана на почти тех же принципах, которые мы использовали в тестовом примере. В следующих статьях мы разберем их более подробно.

avatar
5000
  Подписаться  
Уведомление о