C# - Win Forms - 事件流程周期

时间:2009-08-22 14:37:22

标签: c# .net events delegates

我正在阅读Jon Skeet关于C#的refcard。他说:

  

“事件与代表密切相关,但它们不是一回事。”

因此,根据我的理解,当引发事件时,处理程序(委托)执行代码。

我有以下疑问:

(1)当我们宣布一个事件时,它会在任何“REGISTERS”中注册吗?或“系统注册管理机构”?

(2)Old VB 6.0样式处理没有委托的事件,那么为什么我们不能在没有委托的情况下编写事件呢?

Win Forms的流程如何:如果我单击一个按钮,它将打印hello(以下示例)。

button_click( sender,some event args  )
{
    print();
} 

void print( )
{
    console.WriteLine ("Hello");
}

此事件如何在内部链接和处理? (CLR内部发生了什么?)

(3)阻止事件返回值的事件背后的逻辑是什么?

感谢大家,感谢你度过了黄金时光。

4 个答案:

答案 0 :(得分:4)

delegate 是类型定义。它指定方法必须兼容的签名。

event 是类似属性的类成员,基于委托类型。它提供了封装,唯一的公共操作是Add(+ =)或Remove( - =)一个处理程序。

(1)不,事件未在任何地方登记。但它是处理方法注册的地方。

(2)我不知道VB6是如何工作的,但在.NET中,所有事件都基于代表。

(2b)单击Button时发生的事情是按钮代码检查事件是否为空,然后调用事件(如方法)。该事件遍历其Invocation列表并调用所有已注册的处理程序。

还有一点,当Button处理和处理鼠标和/或键盘事件时,按钮本身就会产生ButtonClick。这些事件来自MessageLoop(Application.Run)。但是在CLR级别上,这只意味着MessageLoop在Button上调用了一个方法(Control.Perform(..))。

(3)您可以编写一个返回值的委托和/或事件。但想想当有多个处理程序时这意味着什么。签名void handler(object sender, Eventargs e)是(强)推荐。

答案 1 :(得分:1)

事件使用委托:

实施

此代码:

public event EventHandler<YourEventArgs> YourEvent;

将编译成这样的东西:

// a private field
private EventHandler<YourEventArgs> YourEvent = null;

// public add_ method
[MethodImpl(MethodImplOptions.Synchronized)]
public void add_YourEvent(EventHandler<YourEventArgs> value)
{
    YourEvent = (EventHandler<YourEventArgs>)
    Delegate.Combine(YourEvent, value);
}

// public remove_ method
[MethodImpl(MethodImplOptions.Synchronized)]
public void remove_YourEvent(EventHandler<YourEventArgs> value)
{
    YourEvent = (EventHandler<YourEventArgs>)
    Delegate.Remove(YourEvent, value);
}

因此,当您声明一个事件时,您实际上声明了这两个函数。如您所见,这些函数包含对委托字段的访问。 这就是为什么你不能为这个事件分配委托价值,只能订阅或取消订阅。

此代码解释了为什么可以使用以下语法声明事件:

public event MyDelegate MyEvent
{
    add
    {
        ...
    }

    remove
    {
        ...
    }
}

1)事件不会注册到任何类型的注册表中。事件的内存(对于私有委托字段)将在堆上分配,因为委托是引用类型。

2)事件是建立在代表之上的,因此如果没有代表,你就无法使用它们。

3)Henk Holterman(+1)及其他人已经回答了第3个问题。

希望这有帮助。

答案 2 :(得分:0)

  1. 我不知道这个...但我的第一个想法是在堆上,因为大多数对象都在那里生活,事件是对象的一部分....但我冒昧地猜测这个一个....

  2. 他们实际上是为你做幕后工作。这是VB的一个特性。

  3. 他们可以拥有多个委托/监听器,并且无法保证何时触发监听器。惯例是使用eventarg对象将信息返回给处理程序。 Why events have no return types in .NET?对此进行了更好的描述。

答案 3 :(得分:0)

1)不,事件处理程序只会在事件中注册(包含处理程序列表)。

2)我对VB6并不是特别精通,但我相当肯定它有类似的机制,因为从本质上讲,Delegate只是一个强类型的方法指针。

在您的示例中,Button.Click事件包含对委托button_click( sender,some event args)的引用,它在事件被触发时调用。它不包含对print的任何引用,只是对它必须调用的方法的引用。

3)由于单个事件可能有多个处理程序(或者根本没有处理程序),因此返回值通常可能是不合逻辑的行为。因此,大多数事件处理程序都返回void。话虽这么说,您可以创建可以有任何签名的自定义事件。 void (object sender, EventArgs e)签名是大多数(如果不是全部)Microsoft事件的基本签名。