Udostępnij za pośrednictwem


Obiekty Delegujące (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. Jednak w przeciwieństwie do wskaźników funkcji delegaty języka Visual Basic są typem referencyjnym opartym na klasie System.Delegate. Delegaty mogą odnosić się zarówno do metod statycznych — które mogą być wywoływane bez określonej instancji klasy — jak i metod instancyjnych.

Delegaty i zdarzenia

Delegaty są przydatne w sytuacjach, w których potrzebny jest pośrednik między procedurą wywołującą a procedurą, która jest wywoływana. 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 podnoszący zdarzenia nie może wiedzieć wcześniej, który program obsługi zdarzeń obsługuje określone zdarzenie. Visual Basic umożliwia dynamiczne kojarzenie procedur obsługi zdarzeń ze zdarzeniami przez automatyczne utworzenie delegata dla Ciebie podczas korzystania z instrukcji AddHandler. Podczas działania delegat przekazuje wywołania do odpowiedniego obsługiwacza zdarzeń.

Chociaż możesz utworzyć własnych delegatów, w większości przypadków program Visual Basic tworzy delegata i zajmuje się szczegółami. Na przykład instrukcja niejawnie definiuje klasę delegata Event o nazwie <EventName>EventHandler jako zagnieżdżoną klasę w klasie zawierającej tę instrukcję Event i z taką samą sygnaturą 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 EventHandlerz odwołaniem do metody Button1_Click wysłanej jako argument. Druga linia jest bardziej wygodnym sposobem, aby zrobić to samo.

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, w którym kompilator 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 delegata bazowego. Poniższa składnia pokazuje, jak:

Delegate Sub DelegateType()
Event AnEvent As DelegateType

Jest to przydatne, gdy chcesz kierować wiele zdarzeń do tego samego elementu obsługującego.

Delegowanie zmiennych i parametrów

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

Załóżmy, że masz na przykład aplikację z ogłoszeniami drobnymi, która zawiera listę z nazwami samochodów. Reklamy są sortowane według nazwy, która jest zwykle nazwą producenta samochodu. Problem może wystąpić, gdy niektóre samochody zawierają rok produkcji przed marką. Problem polega na tym, że wbudowana funkcja sortowania pola listy sortuje tylko według kodów znaków; umieszcza najpierw wszystkie reklamy rozpoczynające się od dat, a następnie reklamy zaczynają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 podczas wykonywania programu przy użyciu delegatów.

Wyrażenia AddressOf i wyrażenia Lambda

Każda klasa delegata definiuje konstruktor, który otrzymuje 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 w czasie kompilacji musi być nazwą klasy lub interfejsu, który zawiera metodę o określonej nazwie, której sygnatura dokładnie odpowiada sygnaturze klasy delegującej. methodName może być albo metodą współdzieloną, albo instancyjną. 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 pokazano zarówno AddressOf, jak i wyrażenia lambda, które są używane do 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. Więcej przykładów wyrażeń lambda i przypisywania AddressOf do delegatów można znaleźć w Zrelaksowanej konwersji delegatów.

Nazwa Opis
Jak wywołać metodę delegata Zawiera przykład pokazujący, jak skojarzyć metodę z delegatem, a następnie wywołać tę metodę za pośrednictwem delegata.
Porady: przekazywanie procedur do innej procedury w Visual Basic Pokazuje, jak używać delegatów do przekazywania jednej procedury do innej procedury.
Rozluźniona konwersja delegatów Opisuje, jak można przypisywać podprogramy i funkcje do delegatów lub procedur obsługi, nawet gdy ich sygnatury nie są identyczne.
Wydarzenia Zawiera omówienie zdarzeń w Visual Basic.