我正在阅读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)阻止事件返回值的事件背后的逻辑是什么?
感谢大家,感谢你度过了黄金时光。
答案 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)
我不知道这个...但我的第一个想法是在堆上,因为大多数对象都在那里生活,事件是对象的一部分....但我冒昧地猜测这个一个....
他们实际上是为你做幕后工作。这是VB的一个特性。
他们可以拥有多个委托/监听器,并且无法保证何时触发监听器。惯例是使用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事件的基本签名。