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

В прошлой статье, посвященной работе с C# я попытался разработать простенький класс для преобразования координат из географической системы в декартову и обратно. При этом, как я и сказал в конце статьи, я рассмотрел далеко не все аспекты работы с классами. Так, например, я обошел стороной темы работы с событиями в классах, хотя этот вопрос (использование событий в классах) является едва ли не ключевым при проектировании приложений. Однако, чтобы плавно перейти к событиям в классах необходимо рассмотреть ещё один тип данных C#делегаты.

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

Делегаты в C#

Итак, что такое делегат, согласно справочнику от Microsoft:

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

Собственно, для тех, кто имел дело с ссылками на методы в Delphi уже после прочтения этого официального определения все должно стать более менее понятным и остается только рассмотреть как эти самые делегаты описываются на языке C# и, в дальнейшем, используются в тех же событиях классов.

Объявляется делегат следующим образом:

public delegate void DelegateName(args);

то есть, вначале идёт один из модификаторов доступа, далее — ключевое слово delegate, затем тип возвращаемого значения (в примере — void, то есть ничего не возвращаем),затем  — имя делегата и в круглых скобках аргументы (перечень параметров).

Объект делегата обычно создается путем указания имени метода, для которого делегат будет служить оболочкой, или с помощью анонимной функции.

Для работы с делегатами в C# можно выделить четыре шага:

  1. Объявить делегат
  2. Создать  метод, на который будет ссылаться делегат
  3. Создать переменную для этого делегата
  4. Вызвать метод делегата.

Первый делегат C#: переписываем «Hello world»

Чтобы понять как работать с делегатами в C#, я решил переписать наше первое приложение «Hello world» с использованием новых для меня знаний, то есть вывести на экран строку «Hello world» при помощи делегатов. В итоге получился следующий код:

using System;
 
namespace DelegateExample
{
    //объявляем делегат
    public delegate void WriteLine(string Text);
 
    class Program
    {
        //создаем метод на ссылка на который будет передаваться делегату
        static void MyDelegeteMethod(string Line)
        {
            Console.WriteLine(Line);
        }
 
        static void Main(string[] args)
        {
            //создаем переменную типа делегата и указываем ссылку на метод
            WriteLine handl = MyDelegeteMethod;
            //вызываем метод
            handl("Hello world!!!");
            Console.ReadLine();
        }
    }
}

В этом примере новым для меня стал модификатор static для метода MyDelegeteMethod. Модификатор static используется для объявления статического члена, принадлежащего собственно типу, а не конкретному объекту, то есть, объявление в C# типа:

static void MyDelegeteMethod(string Line)

аналогично следующему объявлению в Delphi

class procedure(Line: string);

в каком-либо классе.

Использование делегатов в качестве параметров других методов

Так как делегат относится к ссылочному типу данных, то делегаты можно передавать в качестве параметров в других методах. Например, немного усложним наш пример с делегатом и пусть он используется в качестве параметра метода,который складывает два числа:

using System;
 
namespace DelegateExample
{
    //объявляем делегат
    public delegate void WriteLine(string Text);
 
    class Program
    {
        //создаем метод ссылка на который будет передаваться делегату
        static void MyDelegeteMethod(string Line)
        {
            Console.WriteLine(Line);
        }
 
        //в этом методе делегат используется в качестве параметра
        public static void MethodWithCallback(int param1, int param2, WriteLine callback)
        {
            callback("Сумма чисел: " + (param1 + param2).ToString());
        }
 
        static void Main(string[] args)
        {
            //создаем переменную типа делегата и указываем ссылку на метод
            WriteLine handl = MyDelegeteMethod;
            //вызываем метод с делегатом в качестве параметра            
            MethodWithCallback(1,2, handl);
 
            Console.ReadLine();
        }
    }
}

Теперь метод с именем MethodWithCallback использует делегат в качестве параметра и на экран будет выводиться сумма двух чисел.

Многоадресность

Ещё один интересный, на мой взгляд, момент при работе с делегатами в C#. При вызове делегат может вызывать сразу несколько методов. Это называется многоадресностью.

Чтобы добавить в список методов делегата (список вызова) дополнительный метод, необходимо просто добавить два делегата с помощью оператора сложения или назначения сложения («+» или «+=»).

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

using System;
 
namespace DelegateExample
{
    //объявляем делегат для вывода строк в консоль
    public delegate void WriteLine(string Text);
    //объявляем делегат для работы с числами
    public delegate void Calculate(int A, int B, WriteLine callback);
 
    class Program
    {
        //создаем метод ссылка на который будет передаваться делегату WriteLine
        static void MyDelegeteMethod(string Line)
        {
            Console.WriteLine(Line);
        }
                        /*Методы для делегата Calculate*/
 
        //этот метод будет складывать два числа и выводить результат в консоль
        static void Add(int A, int B, WriteLine callback)
        {
            callback("Сумма двух чисел: "+(A + B).ToString());
        }
 
        //этот метод будет умножать два числа
        static void Multiplication(int A, int B, WriteLine callback)
        {
            callback("Произведение двух чисел: " + (A * B).ToString());
        }
 
        //этот метод будет делить два числа 
        static void Division(int A, int B, WriteLine callback)
        {
            callback("Частное двух чисел: " + ((float)A / B).ToString());
        }
 
 
        static void Main(string[] args)
        {
            //создаем переменную для вывода строки
            WriteLine callback;
            callback = MyDelegeteMethod;
            //создаем переменные типа делегата и указываем ссылку на метод
            Calculate d1 = Add;
            Calculate d2 = Multiplication;
            Calculate d3 = Division;
            //назначаем переменной несколько методов
            Calculate handl = d1 + d2 + d3;
 
            handl(1, 2, callback);
 
            Console.ReadLine();
        }
    }
}

Здесь у нас делегат Calculate принимает также в качестве аргумента другой делегат (для вывода строки на экран). В переменной handl мы сложили все три делегата, а затем последовательно вызвали все три метода — сложение, умножение и деление. Результат работы программы на рисунке ниже:

Не лишним будет напомнить про результат деления двух целых чисел. Чтобы на экран не выводился 0 вместо 0,5, первое число было приведено к типу float.

Соответственно, раз мы можем складывать между собой несколько делегатов, то справедливым будет и обратное действие — вычитание. Например, исключить сложение в нашем примере можно вот так:

//просто для примера вызываем метод
callback("Исключаем сложение: ");
//исключаем из списка один из делегатов
handl -= d1;
//повторяем вызовы
handl(3,5,callback);

Итог

Итак, сегодня мы рассмотрели основы работы с делегатами в C#, научились их создавать, передавать делегатам ссылки на методы, складывать и вычитать делегаты и передавать делегаты в качестве параметров для других методов. В принципе, полученных знаний должно хватить, чтобы разобраться с работой с событиями в C#. Хотя, стоит ещё раз подчеркнуть, что делегаты — это достаточно тяжелая тема и разбираться с ней придётся ещё, видимо, ни один раз.

Книжная полка

Описание: практическое руководство познакомит вас с простыми рекомендациями, помогающими писать программное обеспечение, которое легко поддерживать и адаптировать. Написанная консультантами компании Software Improvement Group книга содержит ясные и краткие советы по применению рекомендаций на практике. Примеры для этого издания написаны на языке C#, но существует аналогичная книга с примерами на языке Java.
купить книгу delphi на ЛитРес
Описание: Книга представляет собой сборник советов, алгоритмов и готовых примеров программ на языке C# в среде MS Visual Studio 2005/2008 из различных областей: работа с формами и элементами управления, папками и файлами, мышью и клавиатурой, мультимедиа и графикой, использование технологий WMI и WSH, взаимодействие с MS Office и другими приложениями, работа в локальной сети и Интернете, особенности использования функций Windows API и др.
купить книгу delphi на ЛитРес
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
0 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии