Delegaten (F#)

Ein Delegat stellt einen Funktionsaufruf als Objekt dar. In F# sollten Sie i. d. R. Funktionswerte verwenden, um Funktionen als erstrangige Werte darzustellen. In .NET Framework werden jedoch Delegaten verwendet, und deshalb werden diese bei der Interoperation mit APIs benötigt, die sie erwarten. Beim Erstellen von anderen Bibliotheken, die zur Verwendung von anderen.NET Framework-Sprachen entwickelt wurden, werden sie möglicherweise auch verwendet.

type delegate-typename = delegate of type1 -> type2

Hinweise

In der vorherigen Syntax stellt type1 die Argumenttypen dar, und type2 stellt den Rückgabetyp dar. Auf die von type1 dargestellten Argumenttypen wird automatisch Currying angewendet. Daher empfiehlt es sich, für diesen Typ die Tupelform zu verwenden, wenn die Argumente der Zielfunktion Curry-Argumente sind, und ein Tupel in Klammern für Argumente zu verwenden, die bereits die Tupelform aufweisen. Durch das automatische Currying wird ein Satz von Klammern entfernt, sodass ein Tupelargument vorhanden ist, das mit der Zielmethode übereinstimmt. Die im einzelnen Fall zu verwendende Syntax finden Sie im Codebeispiel.

Delegaten können an F#-Funktionswerte sowie an statische Methoden und an Instanzenmethoden angefügt werden. F#-Funktionswerte können direkt als Argumente übergeben werden, um Konstruktoren zu delegieren. Für eine statische Methode erstellen Sie den Delegaten mit dem Namen der Klasse und der Methode. Für eine Instanzmethode stellen Sie die Objektinstanz und -methode in einem Argument bereit. In beiden Fällen wird der Memberzugriffsoperator (.) verwendet.

Die Invoke-Methode im Delegattyp ruft die gekapselte Funktion auf. Delegaten können auch als Funktionswerte übergeben werden, indem ohne Klammern auf den Namen der Invoke-Methode verwiesen wird.

Im folgenden Code wird die Syntax zum Erstellen von Delegaten, die verschiedene Methoden in einer Klasse darstellen, veranschaulicht. Die Syntax zum Deklarieren und Zuweisen des Delegaten weist geringe Unterschiede auf, je nachdem, ob es sich um eine statische Methode oder eine Instanzmethode handelt und ob ihre Argumente die Tupelform oder die Curry-Form aufweisen.

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)

Im folgenden Code werden einige der Möglichkeiten veranschaulicht, wie Sie mit Delegaten arbeiten können.

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

Die Ausgabe des vorherigen Codebeispiels lautet wie folgt:

aaaaa
bbbbb
ccccc
[|"aaa"; "bbb"|]

Siehe auch

Konzepte

Parameter und Argumente (F#)

Weitere Ressourcen

F#-Sprachreferenz

Ereignisse (F#)