F#运算符"?"

em7*_*m70 15 f# visual-studio-2010

我只是阅读了这个页面上的信息,而一个新的?提到运营商,我很不清楚它的用途是什么.
任何人都可以提供一个快速解释,发布一个代码剪切该如何使用该运算符,并可能提到一个用例?
编辑:这真的很尴尬,我注意到了吗?Don的发行说明中不再提及运算符.知道为什么会这样吗?

Pav*_*aev 31

这个F#版本中有两个新的"特殊"运算符,(?)和(?< - ).它们没有定义,但它们可用于重载,因此您可以自己定义它们.特殊位是它们如何处理它们的第二个操作数:它们要求它是一个有效的F#标识符,但是将它传递给以字符串形式实现操作符的函数.换一种说法:

a?b
Run Code Online (Sandbox Code Playgroud)

是为了:

(?) a "b"
Run Code Online (Sandbox Code Playgroud)

和:

a?b <- c
Run Code Online (Sandbox Code Playgroud)

是为了:

 (?<-) a "b" c
Run Code Online (Sandbox Code Playgroud)

这些运算符的一个非常简单的定义可能是:

let inline (?) (obj: 'a) (propName: string) : 'b =
    let propInfo = typeof<'a>.GetProperty(propName)
    propInfo.GetValue(obj, null) :?> 'b

let inline (?<-) (obj: 'a) (propName: string) (value: 'b) =
    let propInfo = typeof<'a>.GetProperty(propName)
    propInfo.SetValue(obj, value, null)
Run Code Online (Sandbox Code Playgroud)

请注意,由于gettor的返回类型是通用的,因此在大多数情况下,您必须在使用站点指定它,即:

let name = foo?Name : string
Run Code Online (Sandbox Code Playgroud)

虽然你仍然可以进行链式调用(?)(因为(?)的第一个参数也是通用的):

let len = foo?Name?Length : int
Run Code Online (Sandbox Code Playgroud)

另一个更有趣的实现是重用VB提供的CallByName方法:

open Microsoft.VisualBasic    

let inline (?) (obj: 'a) (propName: string) : 'b =
    Interaction.CallByName(obj, propName, CallType.Get, null) :?> 'b //'

let inline (?<-) (obj: 'a) (propName: string) (value: 'b) =
    Interaction.CallByName(obj, propName, CallType.Set, [| (value :> obj) |])
    |> ignore
Run Code Online (Sandbox Code Playgroud)

这样做的好处是它可以正确处理属性和字段,使用IDispatch COM对象等.