デリゲートは、関数呼び出しをオブジェクトとして表します。 F# では、通常、関数の値を使用して、関数をファースト クラスの値として表す必要があります。ただし、デリゲートは .NET Framework で使用されるため、必要な API と相互運用する場合に必要になります。 また、他の .NET Framework 言語から使用できるように設計されたライブラリを作成するときにも使用できます。
構文
type delegate-typename = delegate of type1 -> type2
注釈
前の構文では、 type1
は引数の型または型を表し、 type2
は戻り値の型を表します。
type1
によって表される引数の型は自動的にカリー化されます。 これは、この型では、ターゲット関数の引数がカリー化されている場合はタプル フォームを使用し、既にタプル形式の引数にはかっこで分けたタプルを使用することを示唆しています。 自動カリー処理では、一連のかっこが削除され、ターゲット メソッドに一致するタプル引数が残ります。 各ケースで使用する必要がある構文については、コード例を参照してください。
デリゲートは、F# 関数の値、および静的メソッドまたはインスタンス メソッドにアタッチできます。 F# 関数の値は、デリゲート コンストラクターに引数として直接渡すことができます。 静的メソッドの場合は、クラスとメソッドの名前を使用してデリゲートを構築します。 インスタンス メソッドの場合は、オブジェクト インスタンスとメソッドを 1 つの引数に指定します。 どちらの場合も、メンバー アクセス演算子 (.
) が使用されます。
デリゲート型の 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
こちらも参照ください
.NET