В Visual Basic (VB.NET) делегаты представляют собой тип, содержащий ссылку на метод с определённой сигнатурой, и служат основой для обработки событий. События построены на делегатах, позволяя объектам уведомлять других о произошедших изменениях.
Для стандартных событий используются уже определённые делегаты, например, EventHandler, а для пользовательских — можно определить собственный делегат с нужной сигнатурой:
'Объявление пользовательского делегата и события Public Delegate Sub ChangedEventHandler(sender As Object, e As EventArgs) Public Event Changed As ChangedEventHandler 'Использование события Public Sub OnChanged() RaiseEvent Changed(Me, EventArgs.Empty) End Sub
Тонкости:
Почему событие в Visual Basic нельзя вызвать вне класса, даже если оно объявлено как Public?
Ответ: Несмотря на модификатор доступа Public, событие можно только "подписать" или "отписать" извне класса, но вызвать (RaiseEvent) можно только в пределах класса — это специфика языка, обеспечивающая инкапсуляцию и контроль над рассылкой событий. Например:
Public Class Foo Public Event MyEvent() End Class Dim f As New Foo() ' Так нельзя: f.RaiseEvent MyEvent() — компилятор не даст этого сделать.
История
Проект Windows Forms: Разработчик пытался вызвать событие "DataUpdated" извне класса данных, чтобы обновить UI. Не удалось, событие не было обработано, пришлось рефакторить архитектуру, переделывать логику из-за неправильного понимания области видимости события.
История
Веб-сервис: При объявлении делегата была опущена одна переменная в сигнатуре. Событие подписалось, но вызывалось с ошибкой времени выполнения — подписчик ожидал один аргумент, а вызов шёл с двумя.
История
Плагин к 1С: Разработчики использовали FieldInfo.SetValue для имитации вызова RaiseEvent. Это вызвало рассогласование состояния интерфейса и креш при обновлении сборки.