A delegate represents a function call as an object. In F#, you ordinarily should use function values to represent functions as first-class values; however, delegates are used in the .NET Framework and so are needed when you interoperate with APIs that expect them. They may also be used when authoring libraries designed for use from other .NET Framework languages.
Syntax
F#
typedelegate-typename= delegateof type1 -> type2
Remarks
In the previous syntax, type1 represents the argument type or types and type2 represents the return type. The argument types that are represented by type1 are automatically curried. This suggests that for this type you use a tuple form if the arguments of the target function are curried, and a parenthesized tuple for arguments that are already in the tuple form. The automatic currying removes a set of parentheses, leaving a tuple argument that matches the target method. Refer to the code example for the syntax you should use in each case.
Delegates can be attached to F# function values, and static or instance methods. F# function values can be passed directly as arguments to delegate constructors. For a static method, you construct the delegate by using the name of the class and the method. For an instance method, you provide the object instance and method in one argument. In both cases, the member access operator (.) is used.
The Invoke method on the delegate type calls the encapsulated function. Also, delegates can be passed as function values by referencing the Invoke method name without the parentheses.
The following code shows the syntax for creating delegates that represent various methods in a class. Depending on whether the method is a static method or an instance method, and whether it has arguments in the tuple form or the curried form, the syntax for declaring and assigning the delegate is a little different.
F#
typeTest1() =
staticmember add(a : int, b : int) =
a + b
staticmember 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.typeDelegate1= delegateof (int * int) -> int
// Delegate2 works with curried arguments.typeDelegate2= delegateof 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)
The following code shows some of the different ways you can work with delegates.
F#
typeDelegate1= delegateof int * char -> string
let replicate n c = String.replicate n (string c)
// An F# function value constructed from an unapplied let-bound functionlet function1 = replicate
// A delegate object constructed from an F# function valuelet delObject = Delegate1(function1)
// An F# function value constructed from an unapplied .NET memberlet 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 signaturelet 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
The output of the previous code example is as follows.
Console
aaaaa
bbbbb
ccccc
[|"aaa"; "bbb"|]
Names can be added to delegate parameters like so:
Delegate parameter names are optional and will be shown in the Invoke method. They are not required to match the parameter names in the implementation. They are only allowed for the curried form but not the tupled form.
fs
typeD1= delegateof item1: int * item2: string -> unit
let a = D1(fun a b -> printf "%s" b)
a.Invoke(item2 = "a", item1 = 1) // Calling with named argumentstypeD2= delegateof int * item2: string -> unit // Omitting one namelet b = D2(fun a b -> printf "%s" b)
b.Invoke(1, item2 = "a")
The output of the previous code example is as follows.
Izvor za ovaj sadržaj možete pronaći na GitHubu, gdje možete stvarati i pregledavati probleme i zahtjeve za povlačenjem. Dodatne informacije potražite u našem vodiču za suradnike.
Povratne informacije o proizvodu .NET
.NET je projekt otvorenog koda. Odaberite vezu za slanje povratnih informacija:
Pridružite se seriji susreta kako biste s kolegama programerima i stručnjacima izgradili skalabilna rješenja umjetne inteligencije temeljena na stvarnim slučajevima upotrebe.