Hassan Y. Ansari Ответов: 3

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


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

Что я уже пробовал:

С Делегатом:

using System;
using System.Collections.Generic;

class Pragim
{
    public static void Main()
    {
        List<employee> empList = new List<employee>();
        empList.Add(new Employee() { ID = 1, Name = "A", Salary = 10000, Experience = 3 });
        empList.Add(new Employee() { ID = 1, Name = "B", Salary = 11000, Experience = 7 });
        empList.Add(new Employee() { ID = 1, Name = "C", Salary = 12000, Experience = 3 });
        empList.Add(new Employee() { ID = 1, Name = "D", Salary = 13000, Experience = 5 });
        empList.Add(new Employee() { ID = 1, Name = "E", Salary = 14000, Experience = 4 });

        IsPromotable isPromotable = new IsPromotable(Promote);
        Employee.PromoteEmployee(empList, isPromotable);
        Console.ReadLine();
    }
    public static bool Promote(Employee emp)
    {
        if (emp.Experience >= 5)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

delegate bool IsPromotable(Employee empl);

class Employee
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Salary { get; set; }
    public int Experience { get; set; }

    public static void PromoteEmployee(List<employee> employeeList, IsPromotable IsEligibleToPromote)
    {
        foreach (Employee employee in employeeList)
        {
            if (IsEligibleToPromote(employee))
            {
                Console.WriteLine(employee.Name + " has been promoted");
            }
        }
    }
}




Без Делегата:

using System;
using System.Collections.Generic;

class Pragim
{
    public static void Main()
    {
        List<employee> empList = new List<employee>();
        empList.Add(new Employee() { ID = 1, Name = "A", Salary = 10000, Experience = 3 });
        empList.Add(new Employee() { ID = 1, Name = "B", Salary = 11000, Experience = 7 });
        empList.Add(new Employee() { ID = 1, Name = "C", Salary = 12000, Experience = 3 });
        empList.Add(new Employee() { ID = 1, Name = "D", Salary = 13000, Experience = 5 });
        empList.Add(new Employee() { ID = 1, Name = "E", Salary = 14000, Experience = 4 });

        
        Employee.PromoteEmployee(empList);
        Console.ReadLine();
    }
    public static bool Promote(Employee emp)
    {
        if (emp.Experience >= 5)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

class Employee
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Salary { get; set; }
    public int Experience { get; set; }

    public static void PromoteEmployee(List<employee> employeeList)
    {
        foreach (Employee employee in employeeList)
        {
            if (Pragim.Promote(employee))
            {
                Console.WriteLine(employee.Name + " has been promoted");
            }
        }
    }
}

3 Ответов

Рейтинг:
2

F-ES Sitecore

Делегаты-это указатели на функции, которые позволяют передавать различные методы PromoteEmployee. Так что вы делаете

IsPromotable isPromotable = new IsPromotable(Promote);
Employee.PromoteEmployee(empList, isPromotable);


однако вы могли бы сделать что-то вроде

IsPromotable isPromotable = IsManager ? new IsPromotable(PromoteManager) : new IsPromotable(Promote);
Employee.PromoteEmployee(empList, isPromotable);


Таким образом, вы можете передать ссылку на различные функции в зависимости от ваших требований, и этот метод затем вызывается внутри PromoteEmployee.

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


Рейтинг:
2

OriginalGriff

Делегаты - это сложные люди, и вы можете многое сделать с ними, но во многих случаях разработчики даже не осознают, что они вообще вовлечены ...
Все события основаны на делегатах; делегат-это набор указателей на функции, которые обеспечивают механизм добавления обработчиков:

DynamicArgument da = DynamicArgument.Create();
            da.ArgumentReceived += Application_ArgumentReceived;

private void Application_ArgumentReceived(object sender, DynamicArgument.DynamicArgmentEventArgs e)
    {
    tbData.Text += "\r\n" + e.Argument;
    }
ArgumentReceived это делегат, который добавляет ваш обработчик в цепочку событий так, чтобы при DynamicArgument класс вызывает событие, все методы, которые "подписались" на делегат, будут выполняться по очереди. Но вы действительно не видите этого, пока не начнете создавать свои собственные события для класса - и даже тогда в современном коде сам делегат "скрыт" за слоем абстракции:
/// <summary>
/// Event to indicate program argument available
/// </summary>
public event EventHandler<DynamicArgmentEventArgs> ArgumentReceived;
/// <summary>
/// Called to signal to subscribers that program argument available
/// </summary>
/// <param name="e"></param>
protected virtual void OnArgumentReceived(DynamicArgmentEventArgs e)
    {
    ArgumentReceived?.Invoke(this, e);
    }

Но это не единственное, что вы можете сделать с ними: вы можете использовать массив делегатов для выбора функции для выполнения. switch блок делает: он =использует индекс в массиве делегатов для запуска определенного фрагмента кода вместо того, чтобы делать это if ... else if ... else if ... else.
Вы можете использовать их для передачи определенного метода печати в общую систему: возможно, вы хотите, чтобы один и тот же код генерировал разные результаты для супервайзера и Пеона? Используйте делегат в качестве параметра, и вы можете передать правильный метод, а оставшийся код останется неизменным.

Множество вещей, которые вы можете сделать с ними - большинство из которых вы встретите, когда немного продвинетесь в своем курсе!


BillWoodruff

Я опубликовал "высотный" вид, который, надеюсь, дополняет ваш: в нем есть что-то "скользкое".NET делегирует, что у многих людей есть проблемы с освоением. Я думаю, что часть сложности заключается в том, чтобы отличить "чистый" указатель функции от структуры, которая поддерживает очередь указателей кода подписчика.

OriginalGriff

И он заслуживает +5

BillWoodruff

И ты тоже !

Рейтинг:
0

BillWoodruff

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

Прикрепляем (связываем) обработчик событий к объектам (элементам управления, классам, средствам операционной системы, таким как файловая система): эти обработчики являются ссылками (указателями функций) на исполняемый код (обратные вызовы), упакованный в специальную структуру .NET, называемую делегатом.

Мы пишем делегата как своего рода шаблон, спецификация его параметров и возвращаемого типа. Затем мы связываем (прикрепляем) экземпляр делегата к соответствующему событию триггера, например к щелчку кнопки или изменению наблюдаемой папки/файла.

Как показывает OriginalGriff в своем примере, вы можете определять свои собственные события; существует специальная структура делегатов формы: void delegate(object sender, EventArgs e) это обработчик событий по умолчанию для многих типов событий управления .NET.

Особенностью делегатов является то, что несколько подписчиков/клиентов могут привязываться к одному и тому же делегату, и все они вызываются в порядке FIFO при вызове/выполнении делегата: отсюда и термин "многоадресный" делегат. Абоненты добавляются с помощью специального оператора'+=.

Внутренний список абонентского кода (очередь) напрямую недоступен; чтобы удалить абонентский код, вы должны сохранить ссылку на него, а затем использовать '-= для его удаления. Удалить всех подписчиков становится сложно, и это продвинутая тема.

Существует много других применений делегатов, и C# 3.0 добавил типы "Action", "Func" и "Predicate", которые позволяют использовать их с меньшей сложностью кода.


CHill60

Самое ясное объяснение, которое я когда - либо видел - +5!

BillWoodruff

Спасибо!