Delegaty (Visual Basic)

Delegaty to obiekty odwołujące się do metod. Są one czasami opisywane jako wskaźniki funkcji bezpiecznego typu , ponieważ są one podobne do wskaźników funkcji używanych w innych językach programowania. Ale w przeciwieństwie do wskaźników funkcji, delegaty Visual Basic są typem odwołania w oparciu o klasę System.Delegate. Delegaci mogą odwoływać się do obu metod udostępnionych — metod, które mogą być wywoływane bez określonego wystąpienia klasy — i metod wystąpienia.

Delegaci i zdarzenia

Delegaci są przydatne w sytuacjach, w których potrzebujesz pośrednika między wywoływaną procedurą a wywoływaną procedurą. Na przykład możesz chcieć, aby obiekt, który zgłasza zdarzenia, mógł wywoływać różne programy obsługi zdarzeń w różnych okolicznościach. Niestety obiekt wywołujący zdarzenia nie może wiedzieć przed upływem czasu, który program obsługi zdarzeń obsługuje określone zdarzenie. Visual Basic umożliwia dynamiczne kojarzenie procedur obsługi zdarzeń z zdarzeniami przez utworzenie delegata podczas korzystania z instrukcji AddHandler . W czasie wykonywania delegat przekazuje wywołania do odpowiedniej procedury obsługi zdarzeń.

Chociaż możesz utworzyć własnych delegatów, w większości przypadków Visual Basic tworzy delegata i zajmuje się szczegółami. Na przykład Event instrukcja niejawnie definiuje klasę delegata o nazwie <EventName>EventHandler jako zagnieżdżone klasy klasy zawierającej instrukcję Event i z tym samym podpisem co zdarzenie. Instrukcja AddressOf niejawnie tworzy wystąpienie delegata, które odwołuje się do określonej procedury. Następujące dwa wiersze kodu są równoważne. W pierwszym wierszu zobaczysz jawne utworzenie wystąpienia klasy EventHandler, z odwołaniem do metody Button1_Click wysłanej jako argument. Druga linia jest bardziej wygodnym sposobem na zrobienie tego samego.

AddHandler Button1.Click, New EventHandler(AddressOf Button1_Click)
' The following line of code is shorthand for the previous line.
AddHandler Button1.Click, AddressOf Me.Button1_Click

Możesz użyć skróconego sposobu tworzenia delegatów w dowolnym miejscu kompilatora może określić typ delegata według kontekstu.

Deklarowanie zdarzeń używających istniejącego typu delegata

W niektórych sytuacjach możesz zadeklarować zdarzenie, aby użyć istniejącego typu delegata jako jego podstawowego delegata. Następująca składnia pokazuje, jak:

Delegate Sub DelegateType()
Event AnEvent As DelegateType

Jest to przydatne, gdy chcesz kierować wiele zdarzeń do tej samej procedury obsługi.

Delegowanie zmiennych i parametrów

Można używać delegatów do innych, niezwiązanych z zdarzeniami zadań, takich jak wolne wątki lub procedury, które muszą wywoływać różne wersje funkcji w czasie wykonywania.

Załóżmy na przykład, że masz aplikację ad sklasyfikowaną, która zawiera pole listy z nazwami samochodów. Reklamy są sortowane według tytułu, który jest zwykle marki samochodu. Problem może wystąpić, gdy niektóre samochody obejmują rok samochodu przed make. Problem polega na tym, że wbudowana funkcja sortowania pola listy sortuje tylko według kodów znaków; umieszcza wszystkie reklamy zaczynające się od dat, a następnie reklamy rozpoczynające się od make.

Aby rozwiązać ten problem, można utworzyć procedurę sortowania w klasie, która używa standardowego sortowania alfabetycznego w większości pól listy, ale jest w stanie przełączyć się w czasie wykonywania do niestandardowej procedury sortowania reklam samochodowych. W tym celu należy przekazać niestandardową procedurę sortowania do klasy sortowania w czasie wykonywania przy użyciu delegatów.

Wyrażenia AddressOf i Lambda

Każda klasa delegata definiuje konstruktor, który przekazuje specyfikację metody obiektu. Argument konstruktora delegata musi być odwołaniem do metody lub wyrażenia lambda.

Aby określić odwołanie do metody, użyj następującej składni:

AddressOf [expression.]methodName

Typ expression czasu kompilacji musi być nazwą klasy lub interfejsu, który zawiera metodę określonej nazwy, której podpis jest zgodny z podpisem klasy delegata. Może methodName to być metoda udostępniona lub metoda wystąpienia. Element methodName nie jest opcjonalny, nawet jeśli utworzysz delegata dla domyślnej metody klasy.

Aby określić wyrażenie lambda, użyj następującej składni:

Function ([parm Jako type, parm2 jako type2, ...]) expression

W poniższym przykładzie przedstawiono wyrażenia lambda używane do AddressOf określania odwołania do delegata.

Module Module1

    Sub Main()
        ' Create an instance of InOrderClass and assign values to the properties.
        ' InOrderClass method ShowInOrder displays the numbers in ascending 
        ' or descending order, depending on the comparison method you specify.
        Dim inOrder As New InOrderClass
        inOrder.Num1 = 5
        inOrder.Num2 = 4

        ' Use AddressOf to send a reference to the comparison function you want
        ' to use.
        inOrder.ShowInOrder(AddressOf GreaterThan)
        inOrder.ShowInOrder(AddressOf LessThan)

        ' Use lambda expressions to do the same thing.
        inOrder.ShowInOrder(Function(m, n) m > n)
        inOrder.ShowInOrder(Function(m, n) m < n)
    End Sub

    Function GreaterThan(ByVal num1 As Integer, ByVal num2 As Integer) As Boolean
        Return num1 > num2
    End Function

    Function LessThan(ByVal num1 As Integer, ByVal num2 As Integer) As Boolean
        Return num1 < num2
    End Function

    Class InOrderClass
        ' Define the delegate function for the comparisons.
        Delegate Function CompareNumbers(ByVal num1 As Integer, ByVal num2 As Integer) As Boolean
        ' Display properties in ascending or descending order.
        Sub ShowInOrder(ByVal compare As CompareNumbers)
            If compare(_num1, _num2) Then
                Console.WriteLine(_num1 & "  " & _num2)
            Else
                Console.WriteLine(_num2 & "  " & _num1)
            End If
        End Sub

        Private _num1 As Integer
        Property Num1() As Integer
            Get
                Return _num1
            End Get
            Set(ByVal value As Integer)
                _num1 = value
            End Set
        End Property

        Private _num2 As Integer
        Property Num2() As Integer
            Get
                Return _num2
            End Get
            Set(ByVal value As Integer)
                _num2 = value
            End Set
        End Property
    End Class
End Module

Podpis funkcji musi być zgodny z typem delegata. Aby uzyskać więcej informacji na temat wyrażeń lambda, zobacz Wyrażenia lambda. Aby uzyskać więcej przykładów wyrażeń lambda i AddressOf przypisań do delegatów, zobacz Zrelaksowana konwersja delegatów.

Tytuł Opis
Instrukcje: wywoływanie metody delegata Zawiera przykład pokazujący, jak skojarzyć metodę z pełnomocnikiem, a następnie wywołać tę metodę za pośrednictwem delegata.
Porady: przekazywanie procedur do innej procedury w Visual Basic Pokazuje, jak za pomocą delegatów przekazać jedną procedurę do innej procedury.
Swobodna konwersja delegatów Opisuje sposób przypisywania podsieci i funkcji do delegatów lub procedur obsługi nawet wtedy, gdy ich podpisy nie są identyczne
Zdarzenia Zawiera omówienie zdarzeń w Visual Basic.