.NET事件特殊方法(添加/删除/提升/其他)

时间:2010-12-24 00:39:26

标签: c# .net vb.net events clr

我想知道EventInfo.GetRaiseMethodEventInfo.GetOtherMethods方法。显然,CLR支持4种与事件相关的方法:添加,删除,提升和“其他”。但是在C#中创建的事件只有添加删除 ...我认为在VB中使用了 raise ,因为你必须指定一个{声明自定义事件时的{1}}方法,但显然并非如此:RaiseEvent始终返回null。

那么,有谁知道:

  • 如果从未使用过与事件关联的 raise 方法有什么意义?是否有使用此方法引发事件的特定MSIL指令? (我在操作码中找不到类似的东西)
  • GetRaiseMethod返回的“其他”方法是什么(实际上,不是实际返回的)?他们应该做什么?
  • BCL中是否有实现这些特殊方法的类型?

2 个答案:

答案 0 :(得分:7)

据我所知,加注并没有太多使用,而且我几乎从未见过它。 C ++ / CLI几乎是我所知道的唯一一种语言,可以很容易地声明一个raise方法。例如,请参阅此代码:

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

要回答你的问题,没有操作码来调用事件,编译器只会调用raise方法:

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

就像它发出add_Bar调用一样。

由于C#允许您仅在声明成员事件的类型范围内调用事件,因此无法获得C#代码来调用该raise方法,这也是值得的。所以不,你不会在BCL中发现这样的方法。

对于.other种方法,我从未见过附加到某个事件。而且我只saw them used once for properties,既没有«Inside IL汇编程序»也没有«CLI注释标准»这本书提供了有关它们的任何信息。但基本上,它们允许您将方法附加到属性或事件以在语义上绑定它们。它们既不是addon,也不是removeon,也不是raise方法,但如果语言需要表达,它们将成为事件的一部分。与此同时,发射一个的唯一方法是使用ilasm。

答案 1 :(得分:1)

是的,C#可以使用add / remove重载来注册事件处理程序。 EventInfo是解析类签名时使用的System.Reflection元数据; Visual Basic中的RaiseEvent方法不一定与此方法相同,因为反射为您创建了一种动态调用事件或添加事件处理程序的方法。 RaiseEvent类似于在C#中调用事件,就像一个方法。

(这是一个部分答案,因为你的帖子中有些问题我也不知道答案。)