Использование делегатов в C#

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

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

Использование делегатов в C# на примере своего класса

Мы уже знаем, что такое класс и как его создавать, поэтому наглядное применение делегатов в C# наиболее выгодно продемонстрировать именно при использовании их в классах. Допустим, мы пишем приложение для работы со списком сотрудников организации. Для этого у нас в программе определен класс Person

public class Person
{ 
    public string Name { get; set; }
    public string Surname { get; set; }
    public string Department { get; private set; }
    public byte Age { get; set; }

    public void ChangeDepartmnet(string newDepartment)
    {
        Department = newDepartment;
    }
}

У класса сотрудника определены свойства: имя, фамилия и отдел в котором он работает. При этом, свойство Department у нас доступно извне только для чтения и чтобы изменить название отдела в котором работает сотрудник необходимо вызвать метод ChangeDepartmnet(). Теперь попробуем ответить на такой вопрос: что нам (как пользователям этого класса) потребуется сделать, если  мы захотим изменить логику метода ChangeDepartmnet() , например, вывести в консоль строку с информацией о том, что у сотрудника изменился отдел? Правильно — мы перепишем тело нашего метода. А что, если этот класс будет находится в какой-нибудь библиотеке классов и мы не имеем доступа к исходному коду этого метода? И вот здесь-то и раскрывается преимущество использования делегата в C# — мы можем делегировать выполнение необходимых нам действий другому методу. Перепишем наш класс следующим образом:

public class Person
{
    public delegate void PrintString(string str); //объявили делегат

    PrintString print; //объявили переменную делегата
    
    public string Name { get; set; }
    public string Surname { get; set; }
    public string Department { get; private set; }
    public byte Age { get; set; }

    public void ChangeDepartmnet(string newDepartment)
    {
        Department = newDepartment;
        print?.Invoke($"Отдел работы сотрудника {Name} {Surname} изменен на {newDepartment}");
    }

    public void Register(PrintString printString)
    {
        print += printString;
    }

    public void Unregister(PrintString printString)
    {
        print -= printString;
    }
}

Здесь мы, во-первых, объявили делегат PrintString:

public delegate void PrintString(string str); //объявили делегат

во-вторых, объявили переменную типа делегата:

PrintString print; //объявили переменную делегата

в-третьих, так как давать прямой доступ к переменным класса извне не рекомендуется, то мы создали два метода — для добавления метода к делегату (Register) и снятия метода (Unregister).

в-четвертых, переписали метод ChangeDepartmnet в котором производим вызов делегата в том случае, если он не равен null, то есть переменная делегата ссылается хотя бы на один метод.

Теперь протестируем наш класс:

class Program
{
    //использование делегатов
    static void Main(string[] args)
    {
        Person person = new Person
        {
            Name = "Вася",
            Surname = "Пупкин"
        };
        person.ChangeDepartmnet("Курьерский");
        person.Register(Show);
        person.ChangeDepartmnet("Общий");
    }

    public static void Show(string message)
    {
        Console.WriteLine(message);
    }
}

Здесь мы добавили метод Show в делегат после первого вызова метода ChangeDepartmnet. Следовательно, в консоли мы увидим только такую строку:

Отдел работы сотрудника Вася Пупкин изменен на Общий

Последовательный вызов методов делегата

Опять же, никто нам не запрещает регистрировать несколько методов для делегата, объявленного в нашем классе Person и эти методы последовательно будут вызываться. Перепишем код нашей программы следующим образом:

class Program
 {
     //использование делегатов
     static void Main(string[] args)
     {
         Person person = new Person
         {
             Name = "Вася",
             Surname = "Пупкин"
         };

         person.Register(Show);
         person.Register(ShowRed);
         person.ChangeDepartmnet("Общий");
     }

     public static void Show(string message)
     {
         Console.ResetColor();         
         Console.WriteLine(message);
     }

     public static void ShowRed(string message)
     {
         Console.ForegroundColor = ConsoleColor.Red;
         Console.WriteLine(message);
     }
 }

Теперь переменная делегата содержит ссылки на два метода — Show и ShowRed. Таким образом, в консоль выведется  две строки — одна белого цвета, а вторая — красного. При этом, обратите, внимание, что исходный код класса Person мы не изменяли.

Итого

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

уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
guest
0 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии