ПРОГРАММИРОВАНИЕ01 сентября

Что такое Делегат Си Шарп?

Делегат — это тип, который представляет ссылки на методы с определенным списком параметров и типом возвращаемого значения. При создании экземпляра делегата этот экземпляр можно связать с любым методом с совместимой сигнатурой и типом возвращаемого значения. Метод можно вызвать (активировать) с помощью экземпляра делегата.

Делегаты в Си Шарп играют важную роль.

Можно ли в программировании на C# обойтись без Делегатов?

Ответ и да и нет.

Если вы хотите написать простенькую программу, то без проблем, но если вы собираетесь в проекте реализовать команды и события, то тут уже без применения делегатов обойтись будет очень непросто.

Попробуем разобраться, что такое Делегаты и как сними работать.

Дадим оппределение Делегату

В своей книге «C# 4.0. Полное руководство», Герберт Шилдт - дает такое определение Делегату:

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

Попробуем перевести все это язык, понятный для начинающих программистов.

Для этого перейдем в практическую плоскость, – определим делегат и поясним как он инициализируется и работает.

По сути работа с делегатом состоит из трех шагов:

Внешне это похоже на то как мы работаем с классами, но "под капотом" у делегата лежит другая логика нежели у класса.

1. Объявление делегата – delegate [возвращаемый_тип] [Имя Делегата] (список_параметров);

Делегат объявляется следующей конструкцией:

delegate [возвращаемый_тип] [Имя Делегата] (список_параметров);

Пример:

delegate string MyDelegate (int value);

или

delegate string MyDelegate (string str);

или

delegate int MyDelegate (int value);

В понимании объявления делегата и кроется понимание работы Делегата и его  возможностей.

Подробнее разберем объявление делегата:

Пример:

Объявим делегат

delegate string MyDelegate (int value);

здесь

delegate [возвращаемый_тип] [Имя Делегата] (список_параметров);

где

– delegate - объявляет делегат

– [возвращаемый_тип] - в данном случае string. Важно! – это тип не САМОГО делегата КАК ТАКОВОГО (как мы привыкли в классах), а ТИП возвращаемого значения МЕТОДА, на который сможет (будет) ссылаться этот Делегат.

– MyDelegate - имя Делегата (может быть любым по вашему усмотрению).

– (список_параметров) - СНОВА ВАЖНО! Это ТИП параметров НЕ Делегата как такового (нет аналогии с классами),
а ТИП параметров МЕТОДА, на который будет (может) ссылаться Делегат.

В нашем примере мы объявили делегат delegate sring MyDelegate (int value);

Что это значит?

А это значит, что мы обяъвили делегат delegate с именем MyDelegate.

Определением string указали, что ТИП возвращаемого значения МЕТОДА, с которым бужет работать наш делегат будет string.

А определением (int value) сказали, что наш делегат сможет ссылаться на методы (вызывать методы), принимающие на вход исключительно числовое значение.

Таким образом мы объявили делегат.

Теперь, чтобы с ним работать необходимо выполнить следующий шаг, а именно проиниициализировать объявленный делегат.

2. Инициализация Делегата (создание объекта Делегата).

Инициализация Делегата конструктивно похожана инициализацию класса и выглядит следующим образом.

Пример:

MyDelegate myDelegate = new MyDelegate(MyMethod);

где MyMethod - это метод, на который будет ссылаться делегат.

И наконец, для непосредственной работы с Делегатом мы должны реализовать наш Делегат.

3. Реализация делегата

string str = myDelegate1(value);

где

string str - это параметр принимающий значение, которое вернет МЕТОД вызваный нашим Делегатом
value - это значение (в нашем случае типа int), которое по средством Делегата будет передано МЕТОДУ,
вызванному нашим делегатом.

Для окончательного поимания рассмотрим простейший код:

using System;

namespace TestDelegate
     {
           internal class Program
               {
               static void Main(string[] args)
                   {
                        //3. Инициализация делегата
                        MyDelegate myDelegate = new MyDelegate(MyMethod);

                        //4. Реализация делегата
                        string strDelegate = myDelegate(5);

                        Console.WriteLine("Делегат отработал на: " + strDelegate);
                      }

                        // 1. Объявление делегата
                        delegate string MyDelegate(int value);

                        // 2. Метод (static), на который будет указывать наш делегат
                        static string MyMethod(int value)
                             {
                                string str = value.ToString();
                                return str;
                              }

           }

  }

Код

Код

 

Что такое Делегат в Си Шарп

Примеры:

  • Делегат, представляющий метод, который складывает два числа и возвращает результат:
    delegate int AddNumbers(int value1, int value2);

  • Делегат, представляющий метод, который регистрирует исключение и ничего не возвращает:
    delegate void LogException(Exception ex);

  • Делегат, представляющий функцию, которая преобразует некоторый универсальный тип в string:
    delegate string FormatAsString<T>(T input);

Точно так же, как классы и интерфейсы, мы можем объявлять делегатов вне классов или вложенными в классы. 

Мы можем пометить их privatepublic, или internal.

Что мы можем назначить «делегату»?

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

Например, предположим, что у нас есть следующий делегат и класс:

delegate double MathCalculation(float value1, float value2);

public static class Calculator
{
    public static double AddNumbers(float value1, float value2) => value2 + value2;

    public static double DivideNumbers(float value1, float value2) => value1 / value2;
}

Мы можем присвоить любой метод переменной, объявленной как тип MathCalculation:

MathCalculation add = Calculator.AddNumbers;
MathCalculation divide = Calculator.DivideNumbers;

Как мы «вызываем» делегата?

Вызов метода, на который ссылается делегат, называется вызовом делегата. 

Мы можем сделать это с помощью Invoke метода:

var result = add.Invoke(2, 3);
 
Или без Invoke метода:
var result = divide(100, 3);

Функции, возвращающие функции

Мы также можем возвращать функции из функции. Предположим, мы собираемся фильтровать и сортировать коллекцию, но хотим изменить порядок сортировки на основе переменной. У нас может быть enumдля разных порядков сортировки:

public enum SortPerson { FirstName, LastName, BirthDate }
Когда мы вызываем OrderBy метод LINQ, мы передаем ему функцию, которая возвращает значение для сортировки. 
 
Мы могли бы написать функцию, которая использует переменную и определяет, по какому свойству Person сортировать:
Func<Person, IComparable> GetSortFunction(SortOrder sortOrder)
{
    switch (SortPerson)
    {
        case SortPerson.FirstName:
            return person => person.FirstName;
        case SortPerson.BirthDate:
            return person => person.BirthDate;
        default:
            return person => person.LastName;
    }
}
Затем мы можем использовать эту переменную следующим образом:
IEnumerable<Person> SortAndFilter(IEnumerable<Person> people, SortPerson sortPerson)
{
    var sortFunction = GetSortFunction(sortPerson);
    return people.Where(person => person.Active).OrderBy(sortFunction);
}
Мы возвращаем делегат (a Func<Person, IComparable>) из одной функции и используем его в качестве параметра для другой функции ( OrderBy).
 

Еще о Делегатах в C#

Делегаты в C# часто используются для обработки событий.

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

  1. Имя метода, который вызывает делегат.
  2. Любой аргумент (если есть) метода.
  3. Возвращаемое значение (если есть) метода. 

Определение делегата в C#

Когда вы хотите создать делегата в C#, вы используете ключевое слово delegate.

Имя вашего делегата может быть каким угодно. 

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

 

Определение делегата в C#

Когда вы хотите создать делегата в C#, вы используете ключевое слово delegate.

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

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

public delegate int DelegateName(int x, int y);

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

 

Делегат может ничего не возвращать

Делегат Message может иметь тип void (то есть ничего не возвращать) и не принимать никаких параметров.

Это значит, что этот делегат может указывать на любой МЕТОД, который не принимает никаких параметров и ничего не возвращает.

delegate void Message();
 

Комментарии

Добавить комментарий:

Отметьте что вы не робот

Вернуться наверх