Meghatalmazottak (F#)
A meghatalmazott egy függvényhívást jelöl objektumként. Az F#-ban általában függvényértékeket kell használnia a függvények első osztályú értékekként való megjelenítéséhez; delegáltakat azonban a .NET-keretrendszer használnak, és szükség van rájuk, amikor együttműködik az őket elváró API-kkal. Más .NET-keretrendszer nyelvekből készült kódtárak készítésekor is használhatók.
Syntax
type delegate-typename = delegate of type1 -> type2
Megjegyzések
Az előző szintaxisban type1
az argumentumtípust vagy -típusokat, valamint type2
a visszatérési típust jelöli. A rendszer automatikusan lekonírozza azokat az argumentumtípusokat, amelyeket a type1
rendszer képvisel. Ez arra utal, hogy ehhez a típushoz egy rekordűrlapot kell használnia, ha a célfüggvény argumentumai curriáltak, és zárójeles rekordot a már a rekordűrlapon lévő argumentumokhoz. Az automatikus currying eltávolítja a zárójelek egy készletét, így a célmetódusnak megfelelő rekordargumentum marad. Tekintse meg az egyes esetekben használni kívánt szintaxis kód példáját.
A meghatalmazottak csatolhatók F# függvényértékekhez, valamint statikus vagy példánymetelyekhez. Az F#-függvény értékei közvetlenül argumentumként továbbíthatók a konstruktorok delegálásához. Statikus metódus esetén az osztály és a metódus nevével kell létrehoznia a delegáltat. Példánymetódus esetén egy argumentumban adja meg az objektumpéldányt és a metódust. Mindkét esetben a rendszer a taghozzáférés-operátort (.
) használja.
A Invoke
delegált típus metódusa meghívja a beágyazott függvényt. A meghatalmazottak függvényértékekként is átadhatók, ha zárójelek nélkül hivatkoznak a Meghívás metódus nevére.
Az alábbi kód az osztály különböző metódusait képviselő meghatalmazottak létrehozásának szintaxisát mutatja be. Attól függően, hogy a metódus statikus vagy példánymetódus, és hogy argumentumai vannak-e a rekordűrlapon vagy a curried formában, a meghatalmazott deklarálásának és hozzárendelésének szintaxisa kissé eltérő.
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)
Az alábbi kód a meghatalmazottak által használható különböző módok némelyikét mutatja be.
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
Az előző példakód kimenete a következő.
aaaaa
bbbbb
ccccc
[|"aaa"; "bbb"|]
A delegált paraméterekhez a következőhöz hasonló nevek vehetők fel:
// 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
A delegált paraméternevek megadása nem kötelező, és megjelenik a Invoke
metódusban. Ezek nem szükségesek az implementáció paraméterneveinek egyeztetéséhez. Ezek csak a lekért űrlapon engedélyezettek, a fürtözött űrlapra azonban nem.
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")
Az előző példakód kimenete a következő.
aa