Недопустимое событие EventHandler и Delegate

Пожалуйста, взгляните на приведенный ниже код, который работает так, как я ожидал:

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   событие типа Делегат. Как событие и обработчик могут быть   делегировать?

2
nl ja de
@Robert Harvey, спасибо. Каковы другие типы делегатов?
добавлено автор w0051977, источник
Является ли переменная Test1 событием или делегатом или и тем и другим?
добавлено автор w0051977, источник
Обработчик событий - это особый тип делегата.
добавлено автор Robert Harvey, источник
Те, которые не являются обработчиками событий. :) Вы можете определить тип делегата, имеющий любую подпись, которую вы хотите. Однако, поскольку вы спросили, вот еще один пример, определенный в Framework: Действие .
добавлено автор Robert Harvey, источник
Все события являются делегатами, но события имеют определенную поддержку подписи и компилятора. Например, вы можете RaiseEvent .
добавлено автор Robert Harvey, источник

1 ответы

Как говорили другие, каждый тип делегата является типом, как если бы он был обычным классом. Итак, в вашем примере кода 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 , и события не могут быть подняты/вызваны извне класса, который его определяет.

2
добавлено
Благодарю. Я добавил еще один вопрос об асинхронных вызовах и делегатах здесь: stackoverflow.com/questions/15091839/… , если у вас есть время.
добавлено автор w0051977, источник
DotNetRuChat
DotNetRuChat
2 992 участник(ов)

Чат русскоязычного .NET сообщества http://dotnet.ru/ Вам могут быть интересны: @dotnetchat, @cilchat, @fsharp_chat, @pro_net, @xamarin_russia, @microsoftstackjobs, @uwp_ru Флуд в @dotnettalks

Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

pro.net
pro.net
710 участник(ов)

Обсуждение .NET Framework и всего, что с ним связано. Правила: не флудить не по теме, уважать ваших коллег и никакой рекламы (объявления о вакансиях можно согласовать с @AlexFails). Флудилка: @dotnettalks Участник @proDOT

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot

.NET Talks: Force Push Masters
.NET Talks: Force Push Masters
490 участник(ов)

Свободный чат .NET разработчиков. Правила: t.me/dotnettalks/56823 Вам могут быть интересны: @dotnetruchat, @dotnetchat, @cilchat, @fsharp_chat, @pro_net, @dotnetgroup, @xamarin_russia, @microsoftstackjobs, @uwp_ru http://combot.org/chat/-1001128250813

.NET Chat Убежище
.NET Chat Убежище
246 участник(ов)

Чат .NET разработчиков под эгидой MSK/SPB .NET Community Group Вам могут быть интересны: @fsharp_chat, @dotnetruchat, @cilchat, @xamarin_russia, @microsoftstackjobs, @dotnetgroup Флуд в @dotnettalks

.NET CIL Chat
.NET CIL Chat
54 участник(ов)

.NET CIL (aka IL aka MSIL)