programowanieProgramista VB.NET

Jak w Visual Basic zrealizować pracę z wydarzeniami i delegatami, i czym różni się scenariusz ich użycia dla wydarzeń standardowych i użytkowych?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

W Visual Basic (VB.NET) delegaty stanowią typ, który zawiera referencję do metody o określonej sygnaturze i są podstawą dla obsługi wydarzeń. Wydarzenia zbudowane są na delegatach, co pozwala obiektom powiadamiać inne o następujących zmianach.

Dla standardowych wydarzeń używane są już zdefiniowane delegaty, na przykład EventHandler, a dla wydarzeń użytkowych można określić własny delegat z potrzebną sygnaturą:

'Deklaracja użytkowego delegata i wydarzenia Public Delegate Sub ChangedEventHandler(sender As Object, e As EventArgs) Public Event Changed As ChangedEventHandler 'Używanie wydarzenia Public Sub OnChanged() RaiseEvent Changed(Me, EventArgs.Empty) End Sub

Szczegóły:

  • Wydarzenie można wywołać tylko w obrębie klasy, w której zostało zadeklarowane;
  • Delegaty można łączyć, tworząc łańcuch wywołań;
  • Niespełnienie odpowiedniej sygnatury prowadzi do błędów kompilacji.

Pytanie z podstępem.

Dlaczego w Visual Basic wydarzenia nie można wywołać poza klasą, nawet jeśli jest zadeklarowane jako Public?

Odpowiedź: Pomimo modyfikatora dostępu Public, wydarzenie można tylko "subskrybować" lub "wypisać" z zewnątrz klasy, ale wywołać (RaiseEvent) można tylko w obrębie klasy — to specyfika języka, zapewniająca enkapsulację i kontrolę nad rozsyłaniem wydarzeń. Przykład:

Public Class Foo Public Event MyEvent() End Class Dim f As New Foo() ' Tak nie można: f.RaiseEvent MyEvent() — kompilator nie pozwoli na to zrobić.

Przykłady rzeczywistych błędów z powodu braku znajomości szczegółów tematu.


Historia

Projekt Windows Forms: Programista próbował wywołać wydarzenie "DataUpdated" z zewnątrz klasy danych, aby zaktualizować UI. Nie udało się, wydarzenie nie zostało obsłużone, trzeba było refaktoryzować architekturę, przekształcać logikę z powodu niewłaściwego zrozumienia zakresu widoczności wydarzenia.


Historia

Usługa sieciowa: Podczas deklaracji delegata pominięto jedną zmienną w sygnaturze. Wydarzenie zostało subskrybowane, ale wywoływano je z błędem w czasie wykonywania — subskrybent oczekiwał jednego argumentu, a wywołanie szło z dwoma.


Historia

Plugin do 1C: Programiści użyli FieldInfo.SetValue do symulacji wywołania RaiseEvent. Spowodowało to niespójność stanu interfejsu i awarię przy aktualizacji kompilacji.