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

public delegate double Function(double x);

public delegate void Subroutine(int i);

Делегат – самостоятельный пользовательский тип, он может быть как вложен в другой пользовательский тип (класс, структуру), так и объявлен отдельно. Так как делегат – это тип, то нельзя объявить в одной области видимости два делегата с одинаковыми именами, но разной сигнатурой.

Function F;

Subroutine S;

Переменные делегата инициализируются конкретными методами при использовании конструктора делегата с одним параметром – именем метода (или именем другого делегата). Если делегат инициализируется статическим методом, требуется указать имя класса и имя метода, для инициализации экземплярным методом указывается объект и имя метода.
При этом метод должен обладать подходящей сигнатурой:

F = new Function(ClassName.SomeStaticFunction);

S = new Subroutine(obj.SomeInstanceMethod);

Для инициализации делегата можно использовать упрощённый синтаксис – достаточно указать имя метода без применения new().

F = ClassName.SomeStaticFunction;

S = obj.SomeInstanceMethod;

После того как делегат инициализирован, инкапсулированный в нем метод вызывается с указанием аргументов метода непосредственно после имени переменной-делегата.

Приведём пример работы с делегатами. Создадим класс, содержащий метод расширения для трансформации массива целых чисел:

public static class ArrayHelper
   
{

public static int[]
     Transform(this int[] data, Transformer f)

{

var result = new int[data.Length];

for (int i = 0; i < data.Length; i++)

result[i] = f(data[i]);

return result;

    }

}

public delegate int Transformer(int x);

public class MainClass

{

public static int TimesTwo(int i)
           { return i * 2; }

public int AddFive(int i)
            { return i + 5; }

 

public static void Main()
   
{
      int
[] a = {1, 2, 3};
      Transformer
t = TimesTwo;

        a = a.Transform(t);

var c = new MainClass();

        a = a.Transform(c.AddFive);

  }
}

public static class ArrayHelper

{

   public static int[] Transform(this int[] data,

TransformerDelegate f)

   {

     var result = new int[data.Length];

     for (int i = 0; i < data.Length; i++)

                result[i] = f(data[i]);

     return result;

    }

}

 

 public delegate int TransformerDelegate(int x);

   

 class Program

 {

 public static int TimesTwo(int i) { return i * 2; }

 

   public int AddFive(int i) { return i + 5; }

 

   static void Main(string[] args)

   {

        int[] a = { 1, 2, 3 };

 

        TransformerDelegate t = TimesTwo;

 

        a = a.Transform(t);   // a={2, 4, 6}

 

        var c = new Program();

 

        a = a.Transform(c.AddFive_);  
                             // a={7, 9, 11}

 

        Console.ReadLine();

    }

}

 

public static class ArrayHelper

{

   public static TResult [] Transform<T,TResult>
        (
this T[] data, Transformer<T,TResult> f)

   {

     var result = new TResult[data.Length];

     for (int i = 0; i < data.Length; i++)

                result[i] = f(data[i]);

     return result;

    }

}

 

 public delegate

TResult Transformer<in T, out TResult> (T x);

 class Program

 {

   public static int TimesTwo(int i)
                        { return i * 2; }

 

   public int AddFive(int i) { return i + 5; }

 

   static void Main(string[] args)

   {

     int[] a = { 1, 2, 3 };

 

     Transformer t = TimesTwo;
                            
//тут ошибка – исправьте сами

 

     a = a.Transform(t);   // a={2, 4, 6}

 

     var c = new Program();

 

     a = a.Transform(c.AddFive_);   // a={7, 9, 11}

 

     Console.ReadLine();

    }

}

Групповые делегаты.

 

Групповой делегат объявляется таким же образом, как и обычный. Затем создаётся несколько объектов делегата, и все они связываются с некоторыми методами. После этого используются операция + для объединения делегатов в один групповой делегат

 

     int[] a = { 1, 2, 3 };

      var c = new Program();

      Transformer <int><int> t=TimesTwo,y=c.AddFive, z;

      z=t+y;

 

     a = a.Transform(z);   // a={7, 9, 11}

 
Приложение

Не переставая любезно улыбаться, Сталин сказал, что, поскольку людям Церкви неудобно по своим делам ходить в правительство, а лицам правительственного аппарата неудобно сноситься непосредственно с Патриархией, следует создать пограничный, так сказать, орган — Совет по делам Русской Православной Церкви. «А во главе Совета поставим товарища Карпова,— сказал вождь и с интересом посмотрел в лица стариков в рясах.— Знаете товарища Карпова?» Да, они его знали, слишком хорошо знали.

Патриарх Алексий I и полковник Карпов

Георгий Григорьевич Карпов был начальником как раз того отдела НКВД, который арестовывал и расстреливал церковную братию. Это он ссылал священнослужителей без суда и закрывал храмы, не интересуясь мнением прихожан. Это от его руки обезлюдела и захирела Православная Церковь. Теперь этого Малюту опять сажают на шею Патриархии... Митрополиты испуганно молчали. Наконец Сергий нашел в себе силы промолвить: «Богопоставленный вождь, но ведь он, Карпов, из гонителей наших...» «Правильно,— явно довольный произведенным эффектом, ответил Сталин,— партия приказывала товарищу Карпову быть гонителем, он исполнял волю партии. А теперь мы ему поручим стать вашим охранителем. Я знаю Карпова, он исполнительный товарищ. Ну, стало быть, согласны, чтобы Карпов стоял во главе Совета?» Удерживая вздох, митрополиты закивали головами. Но то была лишь одна, маленькая, совсем крохотная заминка. В остальном же встреча оставила у иерархов самые радостные, если не сказать, светлые, воспоминания. 

delegate string OrthodoxLink();

class Program
{
   
static string Destroy()   {   return "Kill Orthoodx";  }

    static string Protect()   {   return "Protect Orthoodx";  }

    static void Main(string[] args)
   
{
       
OrthodoxLink polk_Karpov = new OrthodoxLink(Destroy);

        Console.WriteLine(polk_Karpov());

        polk_Karpov = Protect;   //упрощенный тип объявления делегата

        Console.WriteLine(polk_Karpov());

        polk_Karpov = delegate() { return "Press Orthodox"; };

        Console.WriteLine(polk_Karpov());

        string ss = "Kill";

        polk_Karpov = delegate() { return ss; };

        Console.WriteLine(polk_Karpov());

        ss = "Protect";

        Console.WriteLine(polk_Karpov());

    }

  }

 }