Почему пытаться понять делегатов хочется пытаться понять природу вселенной? - PullRequest
54 голосов
/ 21 апреля 2010

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

Ответы [ 7 ]

17 голосов
/ 21 апреля 2010

Делегаты - это просто способ передать функцию в переменную.

Вы передаете делегированную функцию для обратного вызова. Например, при выполнении асинхронного ввода-вывода вы передаете делегированную функцию (функцию, которую вы написали с параметром делегата), которая будет вызываться при считывании данных с диска.

4 голосов
/ 21 апреля 2010

Эта статья Криса Селлса может помочь:

.NET Делегаты: A C # Сказка на ночь

4 голосов
/ 21 апреля 2010

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

Bullet
    DamageBullet
    HealBullet
    PoisonBullet
    DoSomethingElseBullet
    PoisonAndThenHealBullet
    FooAndBarBullet
    ....

С этим шаблоном я должен определять новый подкласс каждый раз, когда мне нужно новое поведение в маркере, что является беспорядком и приводит к большому количеству дублированного кода. Вместо этого я решил это с делегатами. Bullet имеет делегат OnHit, который вызывается, когда пуля попадает в объект, и, конечно, я могу сделать этот делегат любым, что мне нравится. Так что теперь я могу создавать пули, как это

new Bullet(DamageDelegate)

Что, очевидно, намного приятнее, чем делать.

В функциональных языках вы склонны видеть намного больше подобных вещей.

3 голосов
/ 21 апреля 2010

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

У всех делегатов есть метод Invoke(...), поэтому, когда у кого-то есть делегат, он может его выполнить, не имея необходимости знать или беспокоиться о том, что на самом деле делает этот метод.

Это особенно полезно для разделения вещей. Каркасы GUI были бы невозможны без этой концепции, потому что Button просто не может ничего знать о вашей программе, в которой вы собираетесь ее использовать, поэтому он не может сам вызывать ваши методы при каждом нажатии. Вместо этого вы должны указать ему, какие методы он должен вызывать при нажатии.

Полагаю, вы знакомы с событиями и регулярно ими пользуетесь. Поле event на самом деле представляет собой список таких делегатов (также называемый многоадресным делегатом). Возможно, все станет яснее, когда мы посмотрим, как мы могли бы «симулировать» события в C #, если бы в нем не было ключевого слова event, а были только (не многоадресные) делегаты:

public class Button : Rectangle
{
    private List<Delegate> _delegatesToNotifyForClick = new List<Delegate>();

    public void PleaseNotifyMeWhenClicked(Delegate d)
    {
        this._delegatesToNotifyForClick.Add(d);
    }

    // ...

    protected void GuiEngineToldMeSomeoneClickedMouseButtonInsideOfMyRectangle()
    {
        foreach (Delegate d in this._delegatesToNotifyForClick)
        {
            d.Invoke(this, this._someArgument);
        }
    }
}

// Then use that button in your form

public class MyForm : Form
{
    public MyForm()
    {
        Button myButton = new Button();
        myButton.PleaseNotifyMeWhenClicked(new Delegate(this.ShowMessage));
    }

    private void ShowMessage()
    {
        MessageBox.Show("I know that the button was clicked! :))))");
    }
 }

Надеюсь, я смогу немного помочь. ; -)

2 голосов
/ 27 апреля 2015

Давай, ребята! Вы все успешно усложнили ДЕЛЕГАТЫ :)!

Я постараюсь оставить здесь подсказку: я понял делегатов, как только я понял вызовы jquery ajax в Javascript. Например: ajax.send (url, data, successcallback, failcallback) является сигнатурой функции. как вы знаете, он отправляет данные на URL-адрес сервера, в качестве ответа, это может быть 200OK или какая-то другая ошибка. В случае любого такого события (успех / неудача), вы хотите выполнить функцию. Таким образом, это действует как заполнитель функции, которая может быть упомянута как в случае успеха, так и в случае неудачи. Этот заполнитель может быть не очень общим - он может принимать набор параметров и может / не может возвращать значение. Эта декларация такого Placeholder, если она сделана в C #, называется CLEEGATE! Поскольку функции javascript не строги с количеством аргументов, вы бы просто увидели их как ЗАМЕНЯЮЩИЕ заполнители ... но в C # есть некоторые STRICT-объявления ... которые сводятся к объявлениям DELEGATE !!

Надеюсь, это поможет!

2 голосов
/ 21 апреля 2010

Может быть, это поможет:

  • Делегат - это тип (определяющий сигнатуру метода)
  • Экземпляр делегата является ссылкой на метод (указатель на функцию AKA)
  • Обратный вызов - это параметр типа делегата
  • Событие является (своего рода) свойством типа делегата

Назначение делегатов состоит в том, что вы можете иметь переменные / поля / параметры / свойства (события), которые «содержат» функцию. Это позволяет вам сохранять / передавать определенную функцию, выбранную вами во время выполнения. Без этого каждый вызов функции должен быть исправлен во время компиляции.

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

  1. простые указатели на функции, как в C / C ++, не были бы безопасными с точки зрения типов, в .NET компилятор фактически генерирует класс вокруг него, а затем пытается скрыть это как можно больше.

  2. делегаты являются краеугольным камнем LINQ, и происходит крутой переход от определения всего в C # 1 через анонимные методы (C # 2) к лямбдам (C # 3).

Просто ознакомьтесь с 1 или 2 стандартными шаблонами.

0 голосов
/ 19 ноября 2017

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

Пример: как его использовать

class program {
 public static void Main) {
  List<Employee> empList = new List<Employee> () {
   new Employee () {Name = "Test1", Experience = 6 },
   new Employee () {Name = "Test2", Experience = 2 },
  }

// delegate point to the actual function
IsPromotable isEligibleToPromote = new IsPromotable(IsEligibleToPromoteEmployee)
Employee emp = new Employee();

// pass the delegate to a method where the delegate will be invoked.
emp.PromoteEmployee(empList, isEligibleToPromote);

// same can be achieved using lambda empression no need to declare delegate 
emp.PromoteEmployee (empList, emply =>emply.Experience > 2);

   // this condition can change at calling end 
   public static bool IsEligibleToPromoteEmployee (emp){
      if (emp.Experience > 5)
       return true;
      else
      return false;
    }
  }
}


public delegate bool IsPromotable(Employee emp);

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

  // conditions changes it can 5, 6 years to promote
  public void PromoteEmployee (List<Employee> employees, IsPromotable isEligibleToPromote) {
  foreach (var employee in employees) {
    // invoke actual function
    if (isEligibleToPromote(employee)){
       Console.WriteLine("Promoted");   
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...