Преимущества использования делегатов?

Я реализовал небольшую библиотеку только для собственного использования. Он не работает должным образом со всеми остальными методами API, но я всегда рад любой помощи :) Вы можете проверить это здесь: https://github.com/estatic/pydatalake-gen2

7
задан Shog9 19 November 2008 в 18:16
поделиться

12 ответов

Делегат, в действительности, раздает ссылку на метод, не объект... Интерфейс является ссылкой на подмножество методов, реализованных объектом...

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

Если, otoh, в некотором методе или компоненте, все, в чем Вы нуждаетесь, является одним из нескольких методов, которые могут быть в любом количестве различных классов, но у всех есть та же подпись, то необходимо использовать делегата.

2
ответ дан 6 December 2019 в 04:44
поделиться

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

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

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

1
ответ дан 6 December 2019 в 04:44
поделиться

Существует два места, что Вы могли использовать делегатов в шаблоне The Observer. Так как я не уверен, к какому Вы обращаетесь, я попытаюсь ответить на обоих.

Первое должно использовать делегатов в предмете вместо списка IObservers. Этот подход кажется намного более чистым при обработке многоадресной передачи, так как Вы в основном имеете

private delegate void UpdateHandler(string message);
private UpdateHandler Update;

public void Register(IObserver observer)
{
    Update+=observer.Update;
}

public void Unregister(IObserver observer)
{
    Update-=observer.Update;
}

public void Notify(string message)
{
    Update(message);
}

вместо

public Subject()
{
    observers = new List<IObserver>();
}

public void Register(IObserver observer)
{
    observers.Add(observer);
}

public void Unregister(IObserver observer)
{
    observers.Remove(observer);
}

public void Notify(string message)
{
    // call update method for every observer
    foreach (IObserver observer in observers)
    {
        observer.Update(message);
    }
}

Если Вы не должны делать что-то специальное и требовать ссылки на весь объект IObserver, я думал бы, что делегаты будут более чистыми.

Второй случай должен использовать делегатов передачи вместо IObervers, например,

public delegate void UpdateHandler(string message);
private UpdateHandler Update;

public void Register(UpdateHandler observerRoutine)
{
    Update+=observerRoutine;
}

public void Unregister(UpdateHandler observerRoutine)
{
    Update-=observerRoutine;
}

public void Notify(string message)
{
    Update(message);
}

С этим Наблюдатели не должны реализовывать интерфейс. Вы могли даже передать в лямбда-выражении. Это изменяется на уровне управления, в значительной степени различие. Хорошо ли это, или плохой ваше дело.

4
ответ дан 6 December 2019 в 04:44
поделиться

Посмотрите на него другой путь. Что преимущество было бы с помощью пользовательского интерфейса иметь по использованию стандартного пути, который поддерживается языком и в синтаксисе и в библиотеке?

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

Не изобретайте велосипед (если текущая версия не повреждается).

1
ответ дан 6 December 2019 в 04:44
поделиться

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

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

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

привет

0
ответ дан 6 December 2019 в 04:44
поделиться

Когда вы можете вызвать метод напрямую, вам не нужен делегат.

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

Вот (очень глупый) пример кода:

enum TaskStatus
{
   Started,
   StillProcessing,
   Finished
}

delegate void CallbackDelegate(Task t, TaskStatus status);

class Task
{
    public void Start(CallbackDelegate callback)
    {
        callback(this, TaskStatus.Started);

        // calculate PI to 1 billion digits
        for (...)
        {
            callback(this, TaskStatus.StillProcessing);
        }

        callback(this, TaskStatus.Finished);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Task t = new Task();
        t.Start(new CallbackDelegate(MyCallbackMethod));
    }

    static void MyCallbackMethod(Task t, TaskStatus status)
    {
        Console.WriteLine("The task status is {0}", status);
    }
}

Как видите, класс Task не знает и не заботится о том, что - в данном случае - делегат принадлежит методу. который выводит на консоль статус задачи. Этот метод также может отправлять статус по сетевому соединению на другой компьютер. И т.д.

27
ответ дан 6 December 2019 в 04:44
поделиться

На самом деле между Sun и Microsoft был интересный спор по поводу делегатов. Хотя Sun заняла довольно жесткую позицию против делегатов, я считаю, что Microsoft сделала еще более решительный аргумент в пользу использования делегатов. Вот сообщения:

http://java.sun.com/docs/white/delegates.html

http://msdn.microsoft.com/en-us/vjsharp/bb188664.aspx

Думаю, вы найдете это чтение интересным ...

1
ответ дан 6 December 2019 в 04:44
поделиться

Вы не думаете как программист.

Возникает вопрос: зачем вам вызывать функцию напрямую , если можно вызывать делегата ?

Известный афоризм Дэвида Уиллера идет: Все проблемы информатики может быть решена другим уровнем косвенное обращение.

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

6
ответ дан 6 December 2019 в 04:44
поделиться

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

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

Рассмотрим любой метод, который принимает делегат. Если бы у вас не было делегата, как бы вы ему что-то передали? И как у вызываемого абонента могут быть какие-либо гарантии относительно его типа?

2
ответ дан 6 December 2019 в 04:44
поделиться

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

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

9
ответ дан 6 December 2019 в 04:44
поделиться

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

22
ответ дан 6 December 2019 в 04:44
поделиться

Я повторяю ответ, который я дал на этот вопрос .

Мне всегда нравилась метафора радиостанции.

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

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

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

2
ответ дан 6 December 2019 в 04:44
поделиться
Другие вопросы по тегам:

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