委派 (Visual Basic)Delegates (Visual Basic)

委派是參考方法的物件。Delegates are objects that refer to methods. 它們有時稱為「型別安全的函式指標」,因為它們類似於其他程式設計語言中使用的函式指標。They are sometimes described as type-safe function pointers because they are similar to function pointers used in other programming languages. 但不同於函式指標,Visual Basic 委派是參考類型,根據類別System.DelegateBut unlike function pointers, Visual Basic delegates are a reference type based on the class System.Delegate. 委派可以同時參考共用的方法 (不需類別的特定執行個體就能呼叫的方法) 和執行個體方法。Delegates can reference both shared methods — methods that can be called without a specific instance of a class — and instance methods.

委派和事件Delegates and Events

當您在呼叫程序與被呼叫程序之間需要一個媒介時,委派就很有用。Delegates are useful in situations where you need an intermediary between a calling procedure and the procedure being called. 例如,您想要讓引發事件的物件能夠在不同環境下呼叫不同的事件處理常式。For example, you might want an object that raises events to be able to call different event handlers under different circumstances. 不過,引發事件的物件無法事先知道哪一個事件處理常式正在處理特定事件。Unfortunately, the object raising the events cannot know ahead of time which event handler is handling a specific event. Visual Basic 可讓您以動態方式產生關聯的事件處理常式與事件藉由建立您的委派,當您使用AddHandler陳述式。Visual Basic lets you dynamically associate event handlers with events by creating a delegate for you when you use the AddHandler statement. 在執行階段,委派會將呼叫轉送到適當的事件處理常式。At run time, the delegate forwards calls to the appropriate event handler.

雖然您可以建立自己的委派,在大部分情況下,Visual Basic 建立委派,並會為您處理的詳細資料。Although you can create your own delegates, in most cases Visual Basic creates the delegate and takes care of the details for you. 例如,Event 陳述式會隱含定義名為 <EventName>EventHandler 的委派類別做為包含 Event 陳述式之類別的巢狀類別,並包含與事件相同的簽章。For example, an Event statement implicitly defines a delegate class named <EventName>EventHandler as a nested class of the class containing the Event statement, and with the same signature as the event. AddressOf 陳述式會隱含建立參考特定程序之委派的執行個體。The AddressOf statement implicitly creates an instance of a delegate that refers to a specific procedure. 下兩行程式碼的用法相同。The following two lines of code are equivalent. 在第一行中,您會看到明確建立了 EventHandler 的執行個體,其中包含對傳送為引數之 Button1_Click 方法的參考。In the first line, you see the explicit creation of an instance of EventHandler, with a reference to method Button1_Click sent as the argument. 第二行則是可執行相同動作的更便捷方法。The second line is a more convenient way to do the same thing.

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

您可以使用在任意處建立委派的速成法,讓編譯器可依內容判斷委派的型別。You can use the shorthand way of creating delegates anywhere the compiler can determine the delegate's type by the context.

宣告使用現有委派型別的事件Declaring Events that Use an Existing Delegate Type

在某些情況下,您可能想要宣告事件,以使用現有的委派型別做為它的基礎委派。In some situations, you may want to declare an event to use an existing delegate type as its underlying delegate. 下列語法示範做法:The following syntax demonstrates how:

Delegate Sub DelegateType()
Event AnEvent As DelegateType

當您想要將多個事件路由傳送到相同的處理常式時,這非常有用。This is useful when you want to route multiple events to the same handler.

委派變數和參數Delegate Variables and Parameters

您可以針對其他與事件無關的工作 (例如無限制執行緒) 使用委派,或搭配需要在執行階段呼叫不同函式版本的程序來使用委派。You can use delegates for other, non-event related tasks, such as free threading or with procedures that need to call different versions of functions at run time.

例如,假設您具有分類廣告應用程式,其中包含具有車名的清單方塊。For example, suppose you have a classified-ad application that includes a list box with the names of cars. 廣告會依標題排序,通常是汽車製造商。The ads are sorted by title, which is normally the make of the car. 當某些汽車在製造商之前包含汽車的年份時,就會發生您可能面臨的問題。A problem you may face occurs when some cars include the year of the car before the make. 問題是清單方塊的內建排序功能只會依照字元碼排序;它會先排序所有以日期開頭的廣告,接著才是以製造商開頭的廣告。The problem is that the built-in sort functionality of the list box sorts only by character codes; it places all the ads starting with dates first, followed by the ads starting with the make.

為了修正此問題,您可以在某個類別中使用排序程序 (該類別會在大部分清單方塊中使用標準的依字母順序排序),但是可以在執行階段切換到自訂排序程序來進行汽車廣告。To fix this, you can create a sort procedure in a class that uses the standard alphabetic sort on most list boxes, but is able to switch at run time to the custom sort procedure for car ads. 若要這樣做,您可以使用委派,在執行階段將自訂排序程序傳遞到排序類別。To do this, you pass the custom sort procedure to the sort class at run time, using delegates.

AddressOf 和 Lambda 運算式AddressOf and Lambda Expressions

每個委派類別會為傳遞的建構函式定義物件方法的規格。Each delegate class defines a constructor that is passed the specification of an object method. 對委派建構函式的引數必須是對方法的參考或 lambda 運算式。An argument to a delegate constructor must be a reference to a method, or a lambda expression.

若要指定對方法的參考,請使用下列語法:To specify a reference to a method, use the following syntax:

AddressOf [expression.]methodNameAddressOf [expression.]methodName

expression 的編譯時期型別必須是類別或介面的名稱,而該類別或介面包含其簽章符合委派類別簽章的特定名稱方法。The compile-time type of the expression must be the name of a class or an interface that contains a method of the specified name whose signature matches the signature of the delegate class. methodName 可以是共用的方法或執行個體方法。The methodName can be either a shared method or an instance method. methodName 不是選擇性的,即使您為類別的預設方法建立了委派也一樣。The methodName is not optional, even if you create a delegate for the default method of the class.

若要指定 lambda 運算式,請使用下列語法:To specify a lambda expression, use the following syntax:

Function ([parm As type, parm2 As type2, ...]) expressionFunction ([parm As type, parm2 As type2, ...]) expression

下列範例示範用來指定委派參考的 AddressOf 和 lambda 運算式。The following example shows both AddressOf and lambda expressions used to specify the reference for a delegate.

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

函式的簽章必須符合委派型別的簽章。The signature of the function must match that of the delegate type. 如需 Lambda 運算式的詳細資訊,請參閱 Lambda 運算式For more information about lambda expressions, see Lambda Expressions. 如需 lambda 運算式以及要委派的 AddressOf 指派的更多範例,請參閱寬鬆委派轉換For more examples of lambda expression and AddressOf assignments to delegates, see Relaxed Delegate Conversion.

標題Title 說明Description
如何:叫用委派方法How to: Invoke a Delegate Method 提供範例,示範如何將方法和委派產生關聯,然後透過委派叫用該方法。Provides an example that shows how to associate a method with a delegate and then invoke that method through the delegate.
如何:傳遞至另一個程序,在 Visual Basic 中的程序How to: Pass Procedures to Another Procedure in Visual Basic 示範如何使用委派,將一個程序傳遞至另一個程序。Demonstrates how to use delegates to pass one procedure to another procedure.
寬鬆委派轉換Relaxed Delegate Conversion 描述即便是 Sub 和函式的簽章不同,如何將它們指派給委派或處理常式。Describes how you can assign subs and functions to delegates or handlers even when their signatures are not identical
事件Events 提供 Visual Basic 中的事件概觀。Provides an overview of events in Visual Basic.