Bagikan melalui


Delegasi (F#)

Delegasi mewakili sebuah panggilan fungsi sebagai sebuah objek. Di F#, Anda biasanya harus menggunakan nilai fungsi untuk mewakili fungsi sebagai nilai kelas-satu; namun, delegasi digunakan dalam .NET Framework, maka ini diperlukan ketika Anda beroperasi dengan API yang mengharapkannya. Mereka juga dapat digunakan saat menulis pustaka yang dirancang untuk digunakan oleh bahasa .NET Framework lainnya.

Sintaks

type delegate-typename = delegate of type1 -> type2

Keterangan

Dalam sintaksis sebelumnya, type1 mewakili jenis atau jenis-jenis argumen dan type2 mewakili jenis pengembalian. Jenis argumen yang diwakili oleh type1 secara otomatis dibuat menjadi curried. Ini menunjukkan bahwa untuk jenis ini, Anda menggunakan formulir tupel jika argumen fungsi target dibuat menjadi curried, dan argumen yang dikurung oleh tupel yang sudah berupa tupel. Currying otomatis menghapus sekumpulan parentesis, meninggalkan argumen tupel yang cocok dengan metode target. Lihat contoh kode untuk sintaksis yang harus Anda gunakan dalam setiap kasus.

Delegasi dapat dilampirkan ke nilai fungsi F#, dan metode statis atau instans. Nilai fungsi F# dapat langsung diteruskan sebagai argumen untuk mendelegasikan konstruktor. Untuk metode statis, Anda membangun delegasi dengan menggunakan nama kelas dan metode. Untuk metode instans, Anda menyediakan instans objek dan metode di dalam satu argumen. Di dalam kedua kasus, operator akses anggota (.) digunakan.

Metode Invoke pada jenis delegasi memanggil fungsi yang dienkapsulasi. Selain itu, delegasi dapat diteruskan sebagai nilai fungsi dengan merujuk nama metode Panggil tanpa parentesis.

Kode berikut ini menunjukkan sintaksis untuk membuat delegasi yang mewakili berbagai metode di dalam satu kelas. Tergantung apakah metodenya adalah metode statis atau metode instans, dan apakah metode tersebut memiliki argumen dalam bentuk tupel atau bentuk curried, sintaksis untuk mendeklarasikan dan menetapkan delegasi sedikit berbeda.

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)

Kode berikut ini menunjukkan beberapa cara yang berbeda untuk bekerja dengan delegasi.

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

Output dari contoh kode sebelumnya adalah sebagai berikut.

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

Nama dapat ditambahkan untuk mendelegasikan parameter seperti:

// 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

Mendelegasikan nama parameter bersifat opsional dan akan ditampilkan dalam Invoke metode . Mereka tidak diperlukan untuk mencocokkan nama parameter dalam implementasi. Mereka hanya diperbolehkan untuk bentuk kurir tetapi bukan bentuk tupled.

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")

Output dari contoh kode sebelumnya adalah sebagai berikut.

aa

Lihat juga