Поделиться через


Делегаты (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"|]

См. также

Основные понятия

Параметры и аргументы (F#)

Другие ресурсы

Справочник по языку F#

События (F#)