C#. Узагальнені делегати

Узагальнені делегати

Перед вивченням даної теми рекомендується ознайомитись з наступними темами:


Зміст


Пошук на інших ресурсах:




1. Узагальнені делегати. Особливості застосування. Синтаксис оголошення узагальненого делегату для декількох типів

У мові C# допускається використання узагальнених делегатів, які отримують параметрами узагальнені типи. Перевага узагальнених делегатів полягає в тому, що створюється типізована узагальнена форма методу, яка потім узгоджується з конкретним методом будь-якого класу. Метод, що узгоджується з узагальненим делегатом повинен мати схожу сигнатуру. Конкретними методами можуть бути як статичні методи, так і методи екземпляру.

Узагальнені делегати дозволяють безпечно викликати будь-які методи, що відповідають його узагальненій формі.

Загальна форма оголошення узагальненого делегату наступна:

delegate return_type DelegateName<T1, T2, ..., TN>(arguments_list);

тут

  • DelegateName – ім’я узагальненого делегату;
  • T1, T2, TN – імена типів, якими оперує делегат;
  • arguments_list – список аргументів, які отримує делегат.

Після такого оголошення можна створювати посилання на узагальнений делегат за наступною формою:

DelegateName<T1, T2, ..., TN> refDelegate<type1, type2, ..., typeN>;

тут

  • DelegateName<T1, T2, …, TN> – ім’я типу узагальненого делегату;
  • refDelegate – ім’я посилання на узагальнений делегат;
  • type1, type2, typeN – імена типів оголошених у програмі або імена базових типів (int, char, string тощо).

Якщо оголошено посилання, то цьому посиланню можна присвоїти ім’я сумісного методу приблизно наступним чином:

refDelegate = obj.MethodName;

тут

  • obj – ім’я екземпляру класу, який містить метод MethodName();
  • MethodName – ім’я методу, який є сумісний з делегатом DelegateName. Поняття “сумісність” означає, що кількість та типи параметрів методу та делегату співпадають.

Після того, як посилання вказує на метод, є можливість викликати цей метод звичним способом

refDelegate(arguments_list);

тут

  • arguments_list – перелік аргументів, що передаються в метод MethodName(), який викликається за посиланням refDelegate.

 

2. Синтаксис оголошення узагальненого делегату для одного типу T

Якщо делегат оголошується тільки для одного узагальненого типу T, то загальна форма такого оголошення наступна

delegate return_type DelegateName<T>(arguments_list);

тут

  • DelegateName – ім’я узагальненого делегату;
  • T – ім’я узагальненого типу делегату;
  • arguments_list – список аргументів, які отримує делегат.

Відповідно оголошення посилання на делегат DelegateName<T> та його використання може бути таким

refDelegate = obj.MethodName;
...
refDelegate(arguments_list);

тут

  • refDelegate – посилання на делегат DelegateName<T>;
  • arguments_list – перелік аргументів, що передаються в метод MethodName.

 

3. Приклад узагальненого делегату, що отримує параметром один тип T

У прикладі оголошується узагальнений делегат Equal<T>, який оперує типом T та отримує два параметри типу T. Делегат повертає значення типу bool, що визначає рівність (нерівність) двох отримуваних параметрів.

Також оголошується клас EqualOperations, який містить реалізацію методів EqualInt(), EqualShort(), EqualString(). Ці методи визначають рівність відповідно для типів int, short та string. Методи є сумісними з типом делегату Equal<T>.

using System;

namespace ConsoleApp19
{
  // Узагальнений делегат
  delegate bool Equal<T>(T value1, T value2);

  // Клас, що містить методи, які є сумісними
  // з делегатом Equal<T>
  class EqualOperations
  {
    // Для типу int
    public bool EqualInt(int value1, int value2)
    {
      return value1 == value2;
    }

    // Для типу short
    public bool EqualShort(short value1, short value2)
    {
      return value1 == value2;
    }

    // Для типу string
    public bool EqualString(string value1, string value2)
    {
      return value1 == value2;
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // 1. Оголосити екземпляр класу EqualOperations
      EqualOperations obj = new EqualOperations();

      // 2. Використання делегату для типу int
      // 2.1. Сконструювати делегат з іменем delInt для типу int
      Equal<int> delInt = obj.EqualInt;

      // 2.2. Викликати метод за делегатом для типу int
      bool equalInt = delInt(5, 5);
      Console.WriteLine("equalInt(5,5) = {0}", equalInt);

      // 3. Використання делегату для типу string
      // 3.1. Сконструювати делегат з іменем delString
      Equal<string> delString = obj.EqualString;

      // 3.2. Викликати метод за делегатом для типу string
      bool equalString = delString("bestprog.net", "bestprog");
      Console.WriteLine("equalString = {0}", equalString);

      Console.ReadKey();
    }
  }
}

Результат виконання програми

equalInt(5,5) = True
equalString = False

 

4. Приклад узагальненого делегату, що отримує параметрами два типи T1, T2

У прикладі оголошується делегат, що використовує два типи T1, T2.

using System;

namespace ConsoleApp19
{
  // Делегат, що використовує два типи T1, T2
  delegate void Operation<T1, T2>(T1 value1, T2 value2);

  // Клас, що містить метод, який узгоджений з делегатом Operation<T1, T2>
  class Methods
  {
    public void Print(int value1, double value2)
    {
      Console.WriteLine("value1 = {0}", value1);
      Console.WriteLine("value2 = {0}", value2);
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // Оголосити екземпляр класу Methods
      Methods obj = new Methods();

      // Оголосити посилання на делегат Operation<T1, T2>
      Operation<int, double> refOp;

      // Присвоїти посиланню refOp адресу методу Print()
      refOp = obj.Print;

      // Викликати метод Print() за посиланням refOp
      refOp(23, 8.89);

      Console.ReadKey();
    }
  }
}

Результат виконання програми

value1 = 23
value2 = 8.89

 

5. Приклад оголошення та використання узагальненого делегату, що узгоджується зі статичними методами

Узагальнений делегат може бути застосований до статичних методів. У прикладі оголошується делегат для забезпечення сумісності зі статичними методами, які реалізують пошук мінімального значення для типів int та double. У функції main() демонструється використання делегату Min<T>.

using System;

namespace ConsoleApp19
{
  // Узагальнений делегат, що отримує масив узагальненого типу T
  // та повертає значення типу T
  delegate T Min<T>(T[] array);

  // Клас, що містить методи пошуку мінімального значення
  // в масиві для різних числових типів
  class MinValues
  {
    // Пошук мінімального значення в масиві типу double
    public static double GetMinDouble(double[] array)
    {
      double min = array[0];
      for (int i = 1; i < array.Length; i++)
        if (min > array[i])
      min = array[i];
      return min;
    }

    // Для типу int
    public static int GetMinInt(int[] array)
    {
      int min = array[0];
      for (int i = 1; i < array.Length; i++)
        if (min > array[i])
          min = array[i];
      return min;
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // 1. Використання делегату Min<T> для типу double.
      // 1.1. Оголосити тестувальний масив типу double
      double[] AD = { 2.3, 2.5, 1.8, 1.1, 2.8, 1.9 };

      // 1.2. Оголосити посилання на делегат Min<T> для типу double
      Min<double> refDouble;

      // 1.3. Присвоїти посиланню статичний метод
      refDouble = MinValues.GetMinDouble;

      // 1.4. Викликати за посиланням refDouble метод GetMinDouble
      double minDouble = refDouble(AD);
      Console.WriteLine("minDouble = {0}", minDouble);

      // 2. Використання делегату для типу int
      // 2.1. Оголосити тестувальний масив
      int[] AI = { 22, 33, 13, 18, 19, 140, 18, 10, 134 };

      // 2.2. Оголосити посилання на делегат Min<T> для типу int
      //      та присвоїти йому статичний метод GetMinInt
      Min<int> refInt = MinValues.GetMinInt;

      // 2.3. Викликати за посиланням refInt метод GetMinInt
      int minInt = refInt(AI);
      Console.WriteLine("minInt = {0}", minInt);

      Console.ReadKey();
    }
  }
}

Після запуску програма видасть наступний результат

minDouble = 1.1
minInt = 10

 


Зв’язані теми