Gemachtigden (F#)
Een gemachtigde vertegenwoordigt een functieaanroep als een object. In F# moet u gewoonlijk functiewaarden gebruiken om functies weer te geven als eersteklas waarden; Gedelegeerden worden echter gebruikt in .NET Framework en zijn dus nodig wanneer u interoperateert met API's die ze verwachten. Ze kunnen ook worden gebruikt bij het ontwerpen van bibliotheken die zijn ontworpen voor gebruik vanuit andere .NET Framework-talen.
Syntaxis
type delegate-typename = delegate of type1 -> type2
Opmerkingen
In de vorige syntaxis type1
vertegenwoordigt u het argumenttype of de typen en type2
vertegenwoordigt u het retourtype. De argumenttypen die worden vertegenwoordigd door type1
, worden automatisch gecureerd. Dit stelt voor dat u voor dit type een tuple-formulier gebruikt als de argumenten van de doelfunctie worden gecureerd en een haakje voor argumenten die zich al in de tuple-vorm bevinden. Het automatisch kerriemen verwijdert een set haakjes, waarbij een tuple-argument wordt achtergelaten dat overeenkomt met de doelmethode. Raadpleeg het codevoorbeeld voor de syntaxis die u in elk geval moet gebruiken.
Gemachtigden kunnen worden gekoppeld aan F#-functiewaarden en statische of exemplaarmethoden. F#-functiewaarden kunnen rechtstreeks worden doorgegeven als argumenten voor het delegeren van constructors. Voor een statische methode maakt u de gemachtigde met behulp van de naam van de klasse en de methode. Voor een instantiemethode geeft u het objectexemplaren en de methode op in één argument. In beide gevallen wordt de operator voor lidtoegang (.
) gebruikt.
Met Invoke
de methode voor het type gedelegeerde wordt de ingekapselde functie aangeroepen. Gedelegeerden kunnen ook worden doorgegeven als functiewaarden door te verwijzen naar de naam van de aanroepmethode zonder de haakjes.
De volgende code toont de syntaxis voor het maken van gemachtigden die verschillende methoden in een klasse vertegenwoordigen. Afhankelijk van of de methode een statische methode of een instantiemethode is en of deze argumenten in het tuple-formulier of de curriede vorm heeft, is de syntaxis voor het declareren en toewijzen van de gemachtigde iets anders.
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)
In de volgende code ziet u enkele van de verschillende manieren waarop u met gemachtigden kunt werken.
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
De uitvoer van het vorige codevoorbeeld is als volgt.
aaaaa
bbbbb
ccccc
[|"aaa"; "bbb"|]
Namen kunnen als volgt worden toegevoegd aan delegeringsparameters:
// 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
Namen van gedelegeerde parameters zijn optioneel en worden weergegeven in de Invoke
methode. Ze hoeven niet overeen te komen met de parameternamen in de implementatie. Ze zijn alleen toegestaan voor het gecureerde formulier, maar niet voor de tupledvorm.
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")
De uitvoer van het vorige codevoorbeeld is als volgt.
aa