委托 (F#)
委托将函数调用表示为对象。 在 F# 中,通常应使用函数值将函数表示为优先值;但在 .NET Framework 中应使用委托,而且在与需要委托的 API 进行互操作时,也需要使用委托。 当创作设计用于其他 .NET Framework 语言的库时可能也会使用它们。
type delegate-typename = delegate of type1 -> type2
备注
在上面的语法中,type1 表示一个或多个参数类型,type2 表示返回类型。 type1 表示的参数类型会自动进行扩充。 这表示,对于此类型,如果扩充目标函数的参数,则使用元组形式;而对于已采用元组形式的参数,则使用用圆括号括起来的元组。 自动扩充将移除一组圆括号,同时保留与目标方法匹配的元组参数。 有关每种情况下应使用的语法,请参考代码示例。
可以将委托附加到 F# 函数值和静态方法或实例方法。 可以将 F# 函数值作为参数直接传递给委托构造函数。 对于静态方法,可以使用类和方法的名称来构造委托。 对于实例方法,可以在一个参数中提供对象实例和方法。 在这两种情况下,均要用到成员访问运算符 (.)。
委托类型上的 Invoke 方法可调用封装的函数。 另外,也可以通过引用 Invoke 方法名(不使用括号)将委托作为函数值进行传递。
下面的代码演示用于创建表示某个类中的各种方法的委托的语法。 根据方法是静态方法还是实例方法,以及方法的参数采用元组形式还是采用扩充形式,用于声明和分配委托的语法会稍有不同。
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 = new Delegate1( Test1.add )
let del2 : Delegate2 = new 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 = new Delegate1( testObject.Add )
let del4 : Delegate2 = new 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 = new 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"|]