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

 


Связанные темы