委派代表函式呼叫做為物件。 在 F# 中,您通常應該使用函式值來將函式表示為一流的值;不過,當您與預期委派的 API 互作時,會使用 .NET Framework,因此需要委派。 撰寫設計供其他 .NET Framework 語言使用的連結庫時,也可以使用它們。
語法
type delegate-typename = delegate of type1 -> type2
備註
在上一個語法中, type1 表示自變數類型或型別,並 type2 表示傳回型別。 所 type1 表示的自變數類型會自動捲曲。 這表示,如果目標函式的自變數已 curried,以及已採用 Tuple 格式之自變數的括弧化 Tuple,則針對此類型使用 Tuple 表單。 自動咖喱會移除一組括弧,留下符合目標方法的 Tuple 自變數。 請參閱程式代碼範例,以取得您應該在每個案例中使用的語法。
委派可以附加至 F# 函式值,以及靜態或實例方法。 F# 函式值可以直接傳遞為委派建構函式的自變數。 如果是靜態方法,您可以使用 類別的名稱和 方法來建構委派。 針對實例方法,您可以在一個自變數中提供對象實例和方法。 在這兩種情況下,都會使用成員存取運算子 (.) 。
委派 Invoke 類型上的 方法會呼叫封裝的函式。 此外,藉由參考 Invoke 方法名稱而不加上括弧,即可傳遞委派作為函式值。
下列程式代碼顯示用來建立代表類別中各種方法之委派的語法。 根據方法是否為靜態方法或實例方法,以及其具有 Tuple 窗體或 curried 窗體中的自變數,宣告和指派委派的語法稍有不同。
type Test1() =
static member add(a : int, b : int) =
a + b
static member add2 (a : int) (b : int) =
a + b
member x.Add(a : int, b : int) =
a + b
member x.Add2 (a : int) (b : int) =
a + b
// Delegate1 works with tuple arguments.
type Delegate1 = delegate of (int * int) -> int
// Delegate2 works with curried arguments.
type Delegate2 = delegate of int * int -> int
let InvokeDelegate1 (dlg: Delegate1) (a: int) (b: int) =
dlg.Invoke(a, b)
let InvokeDelegate2 (dlg: Delegate2) (a: int) (b: int) =
dlg.Invoke(a, b)
// For static methods, use the class name, the dot operator, and the
// name of the static method.
let del1 = Delegate1(Test1.add)
let del2 = Delegate2(Test1.add2)
let testObject = Test1()
// For instance methods, use the instance value name, the dot operator, and the instance method name.
let del3 = Delegate1(testObject.Add)
let del4 = Delegate2(testObject.Add2)
for (a, b) in [ (100, 200); (10, 20) ] do
printfn "%d + %d = %d" a b (InvokeDelegate1 del1 a b)
printfn "%d + %d = %d" a b (InvokeDelegate2 del2 a b)
printfn "%d + %d = %d" a b (InvokeDelegate1 del3 a b)
printfn "%d + %d = %d" a b (InvokeDelegate2 del4 a b)
下列程式代碼顯示一些您可以使用委派的不同方式。
type Delegate1 = delegate of int * char -> string
let replicate n c = String.replicate n (string c)
// An F# function value constructed from an unapplied let-bound function
let function1 = replicate
// A delegate object constructed from an F# function value
let delObject = Delegate1(function1)
// An F# function value constructed from an unapplied .NET member
let functionValue = delObject.Invoke
List.map (fun c -> functionValue(5,c)) ['a'; 'b'; 'c']
|> List.iter (printfn "%s")
// Or if you want to get back the same curried signature
let replicate' n c = delObject.Invoke(n,c)
// You can pass a lambda expression as an argument to a function expecting a compatible delegate type
// System.Array.ConvertAll takes an array and a converter delegate that transforms an element from
// one type to another according to a specified function.
let stringArray = System.Array.ConvertAll([|'a';'b'|], fun c -> replicate' 3 c)
printfn "%A" stringArray
上述程式代碼範例的輸出如下所示。
aaaaa
bbbbb
ccccc
[|"aaa"; "bbb"|]
名稱可以新增至委派參數,如下所示:
// http://www.pinvoke.net/default.aspx/user32/WinEventDelegate.html
type WinEventDelegate = delegate of hWinEventHook:nativeint * eventType:uint32 * hWnd:nativeint * idObject:int * idChild:int * dwEventThread:uint32 * dwmsEventTime:uint32 -> unit
委派參數名稱是選擇性的,將會顯示在方法中 Invoke 。 它們不需要符合實作中的參數名稱。 它們只允許捲曲形式,但不允許 Tupled 窗體。
type D1 = delegate of item1: int * item2: string -> unit
let a = D1(fun a b -> printf "%s" b)
a.Invoke(item2 = "a", item1 = 1) // Calling with named arguments
type D2 = delegate of int * item2: string -> unit // Omitting one name
let b = D2(fun a b -> printf "%s" b)
b.Invoke(1, item2 = "a")
上述程式代碼範例的輸出如下所示。
aa