Сегодня я бы хотел дать теорию по созданию и использованию делегатов.
Потому как очень и очень многие новички в программировании испытывают трудности
при первом знакомстве с данной конструкцией.
Не будем долго разглагольствовать о необходимости применения делегатов, а перейдем сразу к рассмотрению принципа их использования.
Для начала представьте, что нам необходимо в некоторый метод в качестве
параметра передавать другой метод. Собственно, этого достаточно для объяснения необходимости в делегатах.
Итак, для объявления типа-делегата используется следующая конструкция
delegate void MyDelegate();
Указываем ключевое слово delegate, за ни тип возвращаемого значения того метода, который может быть передан в делегат. Остановимся пока на типе void. Далее указываем имя делегата и в паре скобок также можем указать несколько параметров, которые принимает целевой метод. В данном случае наш будущий метод не принмает параметров. Судя по сигнатуре только что созданного делегата мы можем сказать, что любой метод, который может быть передан в делегат не возвращает значения и не принимает ни одного параметра.
Далее, требуется создать объект нашего типа-делегата. Делается это обычным способом используя конструктор:
MyDelegate myDelegate = new MyDelegate(MyMethod);
Здесь в конструктор мы передали имя целевого метода. Заметьте, что мы не указываем всю сигнатуру метода, а лишь его имя. Данный делегат и так знает все о сигнатуре передаваемого ему метода. Более того, нельзя передать в делегат метод, сигнатура которого не соответствует заданной при объявлении типа-делегата.
Ну и для запуска целевого метода следует вызвать объект нашего делегата
myDelegate();
А теперь все вместе:
namespace ConsoleApplication1
{
//создание типа-делегата
delegate void MyDelegate();
class Program
{
static void Main(string[] args)
{
//создание экземпляра делегата
//с передачей имени метода
MyDelegate myDelegate =
new MyDelegate(MyMethod);
//вызов метода делегата
myDelegate();
}
static void MyMethod()
{
Console.WriteLine
("Делегированный метод выполняется");
Console.ReadKey();
}
}
}
Теперь совсем чуть-чуть изменим наш пример для демонстрации работы делегата с методами иной сигнатуры:
namespace ConsoleApplication1
{
//создание типа-делегата
delegate string MyDelegate(int i);
class Program
{
static void Main(string[] args)
{
//создание экземпляра делегата
//с передачей имени метода
MyDelegate myDelegate =
new MyDelegate(MyMethod);
//вызов метода делегата
string result = myDelegate(5);
Console.WriteLine(result);
Console.ReadKey();
}
static string MyMethod(int p)
{
return p.ToString();
}
}
}
Как видим результаты предсказуемы:

Рис 1. Результаты работы программы
Здесь мы объявили тип-делегат, который может вызывать методы, принимающие один параметр типа int и возвращающие тип string. Кстати, если метод принимает несколько парамемтров, то в делегате они указываются через запятую, точно как в методе.
И самое интересное – вызов целевого метода через делегат:
string result = myDelegate(5);
Как видим, мы указали значение входного параметра для целевого метода и получили результат работы метода.
На последок замечу, что сами по себе делегаты не очень то и полезны. Самая их мощь раскрывается при использовании событий, где способность группового вызова методов (не одного, а нескольких по очереди) дает большую гибкость в функциональности приложения. О событиях мы поговорим в следующей статье.