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

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

55
задан Kin 20 April 2010 в 10:07
поделиться

5 ответов

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

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

17
ответ дан 7 November 2019 в 07:31
поделиться

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

.NET Delegates: AC # Bedtime Story

4
ответ дан 4 July 2019 в 23:57
поделиться

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

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

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

Думаю, вы знакомы с событиями и регулярно их используете. Поле события на самом деле представляет собой список таких делегатов (также называемый многоадресным делегатом). Возможно, все станет яснее, когда мы посмотрим, как мы могли бы «моделировать» события в 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! :))))");
    }
 }

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

3
ответ дан 7 November 2019 в 07:31
поделиться

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

Bullet
    DamageBullet
    HealBullet
    PoisonBullet
    DoSomethingElseBullet
    PoisonAndThenHealBullet
    FooAndBarBullet
    ....

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

new Bullet(DamageDelegate)

, что, очевидно, намного лучше.

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

4
ответ дан 7 November 2019 в 07:31
поделиться

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

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

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

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

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

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

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

2
ответ дан 7 November 2019 в 07:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: