请查看下面的代码,该代码可以正常运行:
Partial Class _Default
Inherits System.Web.UI.Page
Delegate Sub TestEventHandler(ByVal o As Object, ByVal e As EventArgs)
Dim alhandler As TestEventHandler = AddressOf TestEventMethod
Public Event Test1 As TestEventHandler
Public Event Test2 As TestEventHandler
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
AddHandler Me.Test1, alhandler
AddHandler Me.Test2, alhandler
RaiseEvent Test1(Me, e)
RaiseEvent Test2(Me, e)
RemoveHandler Me.Test1, alhandler
RaiseEvent Test1(Me, e)
End Sub
Public Sub TestEventMethod(ByVal o As Object, ByVal e As EventArgs)
MsgBox("Test")
End Sub
End Class
我对以下两个陈述感到困惑:
Dim alhandler As TestEventHandler = AddressOf TestEventMethod '1
Public Event Test1 As TestEventHandler '2
1)这就是说alHandler的引用是一个委托 指向函数的地址。 2)这就是说Test1是 Delegate类型的事件。事件和处理程序如何成为一个 委派?
答案 0 :(得分:3)
正如其他人所说,每种类型的委托都是一种类型,就像它是一个普通的类一样。因此,在您的示例代码中,TestEventHandler
是委托类型。 TestEventHandler
变量可以引用任何TestEventHandler
对象,就像任何其他变量可以引用其自身类型的任何对象一样。必须实例化TestEventHandler
个对象,就像任何其他类型的对象一样。
然而,委托是特殊的,因为您使用不同的特殊语法声明它们。例如,如果您有以下方法:
Public Sub MyMethod(Text As String)
' ...
End Sub
您可以创建一个与该方法签名匹配的委托:
Public Delegate Sub MyMethodDelegate(Text As String)
请记住,通过这样做,只需定义MyMethodDelegate
类型。这不会声明该类型的变量,也不会实例化该类型的对象。
然而,VB.NET语法中有两件事情,这往往会造成很多混乱。首先,当您声明一个事件时,您可以使用两种不同的语法:
Public Event MyEvent As MyMethodDelegate
Public Event MyEvent(Text As String)
这两行都做同样的事情。第一行使用已定义的委托类型定义事件。第二行基本上定义了一个新的未命名委托,然后将其用作事件的类型。 (注意,为了简单起见,我使用MyMethodDelegate
,这样可行,但标准规定事件应该有发件人和事件参数。)当声明事件时,请考虑它就像一个变量。在幕后,它就像一个集合对象,它保存了使用AddHandler
函数添加到它的所有委托对象的列表。
VB.NET中第二个令人困惑的事情是,当您使用AddressOf
函数时,编译器将在必要时自动为您实例化一个新的委托对象。所以,例如,当你做这样的事情时:
AddHandler myObject.MyEvent, AddressOf MyMethod
这只是输入全文的快捷方式,如下所示:
AddHandler myObject.MyEvent, New MyMethodDelegate(AddressOf MyMethod)
后者在我看来更清楚。您实际在做的是创建该委托类型的新对象,并将该委托对象指向该方法,然后将该委托对象添加到该事件(该对象的类型定义的类似事件集合的变量)。
所以,在你的例子中,这一行:
Dim alhandler As TestEventHandler = AddressOf TestEventMethod
将更清楚地写为:
Dim alhandler As TestEventHandler = New TestEventHandler(AddressOf TestEventMethod)
它声明一个委托变量,然后将其设置为指向该特定方法的新委托对象。在这种情况下,它只是一个标准的委托变量,而不是一个事件。事件与委托字段/属性非常相似。事件本质上是私有委托字段的访问器包装器,就像属性通常包装私有字段一样。委托字段和事件之间的巨大差异是事件支持AddHandler
和EventHandler
函数,并且不能从定义它的类之外引发/调用事件。