Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Делегат представляет вызов функции в качестве объекта. В 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(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)
В следующем коде показаны некоторые из различных способов работы с делегатами.
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
Выходные данные предыдущего примера кода приведены следующим образом.
aaaaa
bbbbb
ccccc
[|"aaa"; "bbb"|]
Имена можно добавить в параметры делегата, например:
// 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
Имена параметров делегата являются необязательными и будут отображаться в методе Invoke . Они не требуются для сопоставления имен параметров в реализации. Они разрешены только для куриной формы, но не кортежей формы.
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")
Выходные данные предыдущего примера кода приведены следующим образом.
aa