Подтвердить что ты не робот

Специальные события .NET events (add/remove/raise/other)

Мне было интересно о EventInfo.GetRaiseMethod и EventInfo.GetOtherMethods. По-видимому, CLR поддерживает 4 вида методов, связанных с событиями: добавление, удаление, повышение и "другие". Но события, созданные на С#, только добавляются и удаляются... Я предположил, что рейз использовался в VB, так как вы должны указать метод RaiseEvent при объявлении пользовательского события, но, по-видимому, это не так: GetRaiseMethod всегда возвращает null.

Итак, кто-нибудь знает:

  • Какой смысл иметь метод повышения, связанный с событием, если он никогда не использовался? Существует ли конкретная инструкция MSIL для создания события с использованием этого метода? (Я не могу найти ничего подобного в кодах операций)
  • Какие возвращаемые методы "другие" (ну, на самом деле не возвращены) на GetOtherMethods? Что они должны делать?
  • Существуют ли типы BCL, которые реализуют эти специальные методы?
4b9b3361

Ответ 1

Насколько я знаю, рейз не используется много, и я его почти никогда не видел. С++/CLI - это в значительной степени единственный язык, который я знаю, что упрощает объявление метода повышения. См. Этот код, например:

using namespace System;

ref class Foo {

private:
    Action ^bar;

public:
    event Action ^Bar {
        void add (Action ^action)
        {
            Console::WriteLine ("add");
            bar += action;
        }

        void remove (Action ^action)
        {
            Console::WriteLine ("remove");
            bar -= action;
        }

        void raise ()
        {
            Console::WriteLine ("raise");

            if (!bar)
                return;

            Console::WriteLine ("raise for real");
            bar->Invoke ();
        }
    };
};

void hello ()
{
    Console::WriteLine ("hello");
}

void main ()
{
    Foo ^foo = gcnew Foo ();
    foo->Bar ();

    foo->Bar += gcnew Action (&hello);

    foo->Bar ();
}

Что, при запуске, естественно выдает:

C:\tmp>test
raise
add
raise
raise for real
hello

Чтобы ответить на ваш вопрос, нет кода операции для вызова события, компилятор просто испустит вызов метода повышения:

  IL_0020:  ldloc.0
  IL_0021:  call       instance void Foo::raise_Bar()

Так же, как он испускает вызов add_Bar.

Также ничего не стоит, поскольку С# позволяет вызывать событие исключительно в области типа, объявляющего событие-член, вы не можете получить код С# для вызова этого метода raise. Таким образом, нет, вы не найдете такой метод, открытый в BCL.

Что касается методов .other, я никогда не видел привязанных к событию. И я только видел, что они использовались один раз для свойств, и ни одна книга "Inside IL assembler", ни "Аннотированный стандарт CLI" не дают никакой информации о них. Но в основном они позволяют прикрепить методы к свойству или к событию, чтобы связать их семантически. Они не являются ни addon, ни removeon, ни методом raise, но они будут частью события, если язык должен это выразить. Тем временем единственный способ испускать один - использовать ilasm.

Ответ 2

Да, С# может использовать перегрузки add/remove для регистрации обработчиков событий. EventInfo - метаданные System.Reflection, которые используются при анализе подписи класса; метод RaiseEvent в Visual Basic не обязательно тот же метод, что и этот, поскольку отражение создает способ динамического вызова события или добавления обработчика события. RaiseEvent похож на вызов события в С#, как метод.

(Это частичный ответ, так как в вашем посте есть вопросы, я тоже не знаю ответа.)