Temsilciler (F#)

Temsilci bir işlev çağrısını nesne olarak temsil eder. F# dilinde normalde işlevleri birinci sınıf değerler olarak göstermek için işlev değerlerini kullanmanız gerekir; ancak, temsilciler .NET Framework'te kullanılır ve bu nedenle onları bekleyen API'lerle birlikte çalışırken gereklidir. Bunlar, diğer .NET Framework dillerinden kullanılmak üzere tasarlanmış kitaplıklar yazılırken de kullanılabilir.

Sözdizimi

type delegate-typename = delegate of type1 -> type2

Açıklamalar

Önceki söz diziminde bağımsız type1 değişken türünü veya türlerini temsil eder ve type2 dönüş türünü temsil eder. tarafından type1 temsil edilen bağımsız değişken türleri otomatik olarak oluşturulur. Bu, hedef işlevin bağımsız değişkenleri curried ise bu tür için bir tanımlama grubu formu ve zaten tanımlama grubu formunda olan bağımsız değişkenler için parantez içine alınmış bir tanımlama grubu kullanmanızı önerir. Otomatik currying, bir dizi parantezi kaldırarak hedef yöntemle eşleşen bir tanımlama grubu bağımsız değişkeni bırakır. Her durumda kullanmanız gereken söz diziminin kod örneğine bakın.

Temsilciler F# işlev değerlerine ve statik veya örnek yöntemlerine eklenebilir. F# işlev değerleri doğrudan temsilci oluşturucularına bağımsız değişken olarak geçirilebilir. Statik bir yöntem için, sınıfın adını ve yöntemini kullanarak temsilciyi oluşturursunuz. Bir örnek yöntemi için nesne örneğini ve yöntemini tek bir bağımsız değişkende sağlarsınız. Her iki durumda da üye erişim işleci (.) kullanılır.

Temsilci Invoke türündeki yöntemi kapsüllenmiş işlevi çağırır. Ayrıca, parantezler olmadan Invoke yöntemi adına başvurarak temsilciler işlev değerleri olarak geçirilebilir.

Aşağıdaki kod, bir sınıftaki çeşitli yöntemleri temsil eden temsilciler oluşturmaya yönelik söz dizimini gösterir. Yöntemin statik bir yöntem mi yoksa örnek yöntemi mi olduğuna ve tanımlama grubu formunda mı yoksa curried formunda mı bağımsız değişkenleri olduğuna bağlı olarak, temsilciyi bildirme ve atama söz dizimi biraz farklıdır.

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)

Aşağıdaki kod, temsilcilerle çalışabileceğiniz farklı yollardan bazılarını gösterir.

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

Önceki kod örneğinin çıktısı aşağıdaki gibidir.

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

Temsilci parametrelerine adlar eklenebilir, örneğin:

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

Temsilci parametre adları isteğe bağlıdır ve yönteminde Invoke gösterilir. Uygulamadaki parametre adlarını eşleştirmeleri gerekmez. Yalnızca curried forma izin verilir, ancak kümelenmiş forma izin verilmez.

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

Önceki kod örneğinin çıktısı aşağıdaki gibidir.

aa

Ayrıca bkz.