Делегаты и обратные вызовы - PullRequest
6 голосов
/ 17 ноября 2009

Означает ли термин обратный вызов в контексте делегатов: « делегат, делегирующий его, работает другому поручению делегата для завершения некоторой задачи »?

Пример: ( Исходя из моего понимания, я реализовал обратный вызов, исправьте меня, если он неверен )

namespace Test
{
    public delegate string CallbackDemo(string str);  

    class Program
    {
        static void Main(string[] args)
        {
            CallbackDemo handler = new CallbackDemo(StrAnother);
            string substr = Strfunc(handler);
            Console.WriteLine(substr);
            Console.ReadKey(true);
        }

        static string Strfunc(CallbackDemo callback)
        {
           return callback("Hello World");   
        }

        static string StrAnother(string str)
        {
            return str.Substring(1, 3).ToString();
        }
    }
}

При необходимости приведите примеры.

Ответы [ 4 ]

11 голосов
/ 17 ноября 2009

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

namespace Test
{
    //In this case, this delegate declaration is like specifying a specific kind of function that must be used with events.
    public delegate string CallbackDemo(string str);
    class Program
    {
        public static event CallbackDemo OnFoobared;
        static void Main(string[] args)
        {
            //this means that StrAnother is "subscribing" to the event, in other words it gets called when the event is fired
            OnFoobared += StrAnother;
            string substr = Strfunc();
            Console.WriteLine(substr);
            Console.ReadKey(true);
            //this is the other use of delegates, in this case they are being used as an "anonymous function". 
            //This one takes no parameters and returns void, and it's equivalent to the function declaration 
            //'void myMethod() { Console.WriteLine("another use of a delegate"); }'
            Action myCode = delegate
            {
                Console.WriteLine("another use of a delegate");
            };
            myCode();
            Console.ReadKey(true);
            //the previous 4 lines are equivalent to the following however this is generally what you should use if you can
            //its called a lambda expression but it's basically a way to toss arbitrary code around
            //read more at http://www.developer.com/net/csharp/article.php/3598381/The-New-Lambda-Expressions-Feature-in-C-30.htm or 
            ///127523/c-lyambda-vyrazheniya-zachem-ih-ispolzovat
            Action myCode2 = () => Console.WriteLine("a lambda expression");
            myCode2();
            Console.ReadKey(true);
        }

        static string Strfunc()
        {
            return OnFoobared("a use of a delegate (with an event)");
        }
        static string StrAnother(string str)
        {
            return str.Substring(1, 3).ToString();
        }
    }
}

Я только поцарапал поверхность здесь; переполнение стека поиска для "делегата c #" и "лямбда-выражения c #" для многих других!

5 голосов
/ 17 ноября 2009

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

public static void Main(string[] args)
{
    Socket s = new Socket(...);

    byte[] buffer = new byte[10];
    s.BeginReceive(buffer, 0, 10, SocketFlags.None, new AsyncCallback(OnMessageReceived), buffer);

    Console.ReadKey();
}

public static void OnMessageReceived(IAsyncResult result)
{
    // ...
}

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

3 голосов
/ 17 ноября 2009

Обратный вызов - это, по сути, делегат, переданный в процедуру, которую эта процедура будет «перезванивать» в какой-то подходящий момент. Например, в асинхронных вызовах, таких как WebRequest.BeginGetResponse или операция WCF BeginXxx, вы должны передать AsyncCallback. Рабочий «перезвонит» любому методу, который вы передаете как AsyncCallback, в этом случае, когда он закончен, чтобы сообщить вам, что он завершен, и получить результат.

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

1 голос
/ 09 апреля 2015

За это проголосуют именно потому, что это правильно. C # не реализует делегатов, он реализует переадресацию вызовов. Это неправильное использование номенклатуры, вероятно, самая большая проблема с C # в этом отношении.

Документ ACM, представленный ниже, является первым описанием того, что позже будет называться делегатом. По сути, делегат - это то, что кажется экземпляром объекта (то, как он на самом деле реализован, не имеет значения). Это означает, что вы можете вызывать методы, обращаться к свойствам и т. Д. Из делегата.

http://web.media.mit.edu/~lieber/Lieberary/OOP/Delegation/Delegation.html

В C # реализованы обратные вызовы или переадресация вызовов (все зависит от того, как вы их используете). Это не делегаты. Чтобы быть делегатом, нужно иметь доступ к объекту, как если бы это был сам объект.

Когда ручка передает сообщение обрисовки прототипу, оно говорит: «Я не знаю, как обрабатывать сообщение об отрисовке. Я бы хотел, чтобы вы ответили мне, если можете, но если у вас есть какие-либо дополнительные вопросы, например, какова стоимость моей переменной x, или вам нужно что-то сделать, вы должны вернуться ко мне и спросить ». Если сообщение Далее делегируется, все вопросы о значениях переменных или запросах ответа на сообщения все выводятся объекту, который делегировал сообщение в первую очередь. - Генри Либерман

Так, как это испортилось? Если честно, я не знаю. Я действительно знаю, что использую делегаты (уже более 16 лет) задолго до C # и то, что реализует C #, не является делегатами.

Здесь можно найти действительно хорошее объяснение.

http://www.saturnflyer.com/blog/jim/2012/07/06/the-gang-of-four-is-wrong-and-you-dont-understand-delegation/

Реальное делегирование - это больше, чем создание обратных вызовов или переадресация вызовов. Настоящий делегат позволяет мне вызывать любой метод для этого объекта, получать и / или устанавливать общедоступные свойства и т. Д. - все как если бы это был сам объект. Это гораздо мощнее и проще в использовании, чем «делегирование» в C #.

ОП спросил:

Означает ли термин обратный вызов в контексте делегатов: «делегат, делегирующий его, работает с другим поручением делегата для завершения некоторой задачи»?

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

Относительно того, почему делегирование было повреждено, я понятия не имею. Я с нетерпением жду, когда C # осуществит делегирование TRUE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...