Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Принцип работы функций обратного вызова, callback function 
:(
    Опции темы
Medved
Дата 4.7.2005, 05:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 3
Всего: 154



Объясните мне пожалуйста принцип работы функций обратного вызова.


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
Domestic Cat
Дата 4.7.2005, 08:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 9
Всего: 172



Полный код
Код

using System;
class MyClass
{
    public delegate int CallbackDelegate(string arg);

    public static void Main()
    {
        MyClass myClass = new MyClass();
        CallbackDelegate myDelegate = new CallbackDelegate (myClass.MyCallbackMethod);
        int result = myDelegate("Hello, World");
        Console.WriteLine(result);
    }
           
    int MyCallbackMethod(String s)
    {
        return s.Length;
    }
}

//(код не проверял)

1. Объявляется делегат:
Код

class MyClass
{
         public int delegate CallbackDelegate (string arg);


2. Объявляется метод с той же сигнатурой, что и делегат, т.е. с тем же возвращаемым значением и аргументами
Код

         int MyCallbackMethod(String s)
         {
                 return s.Length;
         }


3. Создается объекта класса, который содержит нужный метод
Код

MyClass myClass = new MyClass();


4. Создается сам объект-делегат, которому передается ссылка на метод
Код

CallbackDelegate myDelegate = new CallbackDelegate (myClass.MyCallbackMethod);


5. Вызывается делегат
Код

int result = delegate("Hello, World");


Делегат - это по сути дела класс, наследющий от Delegate\ При создании делегата ему передается ссылка на метод (то же самое что и в С, но "безопасное",
т.е. ссылку на метод "самому" пользовать нельзя, только через делегат). Можно передавать ссылку на статик метод, или инстанс метод, как в данном случае. Главное чтоб сигнатура совпадала.
При этом генерируется класс, содержащий ссылку на данный метод, плюс ряд вспомогательных методов, для асинхронного вызова и т п; и далее создается объект этого класса (myDelegate).
У данного объекта есть метод DynamicInvoke(), который вызывает переданный делегату метод. Для упрощения этот метод можно вызывать просто myDelegate(/*аргументы*/).
Например, то же самое, что и в примере, можно было бы сделать так
Код

int result = (int) myDelegate.DynamicInvoke(new object[] {"Hello, World"});

Сокращение позволяет рассматривать объект делегат как "метод", т.е. вызывать delegate("Hello, World").

Делегаты можно комбинировать, класс делегата может хранить ссылки на любое число методов, главное чтобы сигнатуры были одинаковы:
Код

        myDelegate += new CallbackDelegate (myClass.MyCallbackMethod);
        myDelegate += new CallbackDelegate (myClass.MyCallbackMethod);
        myDelegate += new CallbackDelegate (myClass.MyCallbackMethod);

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





--------------------

PM   Вверх
Medved
Дата 4.7.2005, 14:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 3
Всего: 154



thx.


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
Medved
Дата 4.7.2005, 15:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 3
Всего: 154



Вообще если честно, то меня интересует сам принцип. Т.е. как разработчики .NET обеспечили возможность использования делегатов. Как это рабоает на самом низком уровне.


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
Дрон
Дата 4.7.2005, 17:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 24
Всего: 93



Цитата(Pegas @ 4.7.2005, 16:29)
Т.е. как разработчики .NET обеспечили возможность использования делегатов. Как это рабоает на самом низком уровне.

Только Гейтс это знает smile

Хотя, можно предположить, что примерно так:

Код

using System;
using System.Reflection;

namespace ConsoleApplication1
{
    public class MyDelegate
    {
        object Target;
        MethodInfo Mtd;

        public MyDelegate(object Target, MethodInfo Mtd)
        {
            this.Target = Target;
            this.Mtd = Mtd;
        }

        public void Invoke()
        {
            Mtd.Invoke(Target,null);
        }
    }

    class Class1
    {
        public void SomeMethod()
        {
            Console.WriteLine("SomeMethod called");
        }

        public void Test()
        {
            MyDelegate dlg = new MyDelegate(this,Assembly.GetExecutingAssembly().GetType("ConsoleApplication1.Class1").GetMethod("SomeMethod"));
            dlg.Invoke();
        }

        public Class1()
        {
        }

        [STAThread]
        static void Main(string[] args)
        {
            Class1 cls = new Class1();
            cls.Test();

            Console.ReadLine();
        }
    }
}


Для не public методов нужно ещё учесть это
Цитата
If the requested type is non-public and the caller does not have ReflectionPermission to reflect non-public objects outside the current assembly, this method returns a null reference (Nothing in Visual Basic).


И т.п.



--------------------
Да. Именно так.
PM   Вверх
Medved
Дата 4.7.2005, 17:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 3
Всего: 154



Хорошо, задам вопрос по другому.

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

Как мне это реализовать? Может кто-нибудь объяснить теорию?


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
Дрон
Дата 4.7.2005, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 24
Всего: 93



Pegas
Странный вопрос.

Для реализации этого в Си используются указатели на функции. В C# - рефлекшн.

С точки зрения компилятора Си, в переменную просто сохраняется адрес в памяти, по которому находится нужная функция, в С# сохраняется какая-то информация из метаданных.

Я, похоже, просто не понимаю в чём проблема.

Это сообщение отредактировал(а) Дрон - 4.7.2005, 17:43


--------------------
Да. Именно так.
PM   Вверх
Medved
Дата 4.7.2005, 18:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 3
Всего: 154



Цитата
С точки зрения компилятора Си, в переменную просто сохраняется адрес в памяти, по которому находится нужная функция, в С# сохраняется какая-то информация из метаданных.


В каком формате?


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
Дрон
Дата 4.7.2005, 18:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 24
Всего: 93



В Си это просто 32-битное число -- адрес smile
Ну и на этапе компиляции ещё сверяется соответствие типов данных (возвращаемое значение и параметры)

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

Кстати, до C# точно такая же штука была в C++ Builder и называлась closure.

Вот.
Добавлено @ 18:21
Дрон
Конкретная реализация хранения ссылки на метод в C# от нас скрыта.

Либо там хранится какой-то внутренний указатель (число). Что вероятно, но вызывает сомнения.
Либо там хранится просто описание вроде "ConsoleApplication1.Class1.SomeMethod", которого достаточно благодаря метаданным.

Это сообщение отредактировал(а) Дрон - 4.7.2005, 18:21


--------------------
Да. Именно так.
PM   Вверх
Дрон
Дата 4.7.2005, 18:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Java-ненавистник :)
****


Профиль
Группа: Участник Клуба
Сообщений: 3179
Регистрация: 29.12.2002
Где: Санкт-Петербург

Репутация: 24
Всего: 93



Вот что пишет MSDN
Цитата
Delegates enable scenarios that other languages — such as C++, Pascal, and Modula — have addressed with function pointers. Unlike C++ function pointers, however, delegates are fully object oriented, and unlike C++ pointers to member functions, delegates encapsulate both an object instance and a method.

A delegate declaration defines a class that is derived from the class System.Delegate. A delegate instance encapsulates an invocation list, which is a list one or more methods, each of which is referred to as a callable entity. For instance methods, a callable entity consists of an instance and a method on that instance. For static methods, a callable entity consists of just a method. Invoking a delegate instance with an appropriate set of arguments causes each of the delegate's callable entities to be invoked with the given set of arguments.



--------------------
Да. Именно так.
PM   Вверх
Medved
Дата 4.7.2005, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 7209
Регистрация: 15.9.2002
Где: Kazakhstan, Astan a

Репутация: 3
Всего: 154



Спасибо.


--------------------
http://extreme.sport-express.ru/
...и неважно сколько падал, важно сколько ты вставал...
PM MAIL WWW ICQ Skype GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0825 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.