F#运算符“?”

时间:2009-05-20 23:50:33

标签: visual-studio-2010 f#

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

3 个答案:

答案 0 :(得分:31)

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

a?b

被玷污了:

(?) a "b"

a?b <- c

被玷污了:

 (?<-) a "b" c

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

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)

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

let name = foo?Name : string

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

let len = foo?Name?Length : int

另一个更有趣的实现是重用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

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

答案 1 :(得分:4)

听起来像是“?”运算符与动态语言运行时(DLR)有关。也就是说,当你想在运行时而不是在编译时绑定到对象成员(方法,属性)时,可以使用它。

这很有趣,因为我希望这也是动态成员调用在C#中的工作原理。唉,C#通过“伪”类型(“动态”IIRC)公开此功能。在我看来,这使得代码不太清楚(因为你必须追踪变量声明以了解调用是早期绑定还是后期绑定)。

我不知道确切的语法,但如果我不得不猜测,它会替换或增加“。”。 (点)运算符。如:

let x = foo?Bar()

或者也许:

let x = foo.?Bar()

答案 2 :(得分:1)

在nuget上有一个模块FSharp.Interop.Dynamic,它使用dlr实现动态运算符。

let ex1 = ExpandoObject() in
ex1?Test<-"Hi";
ex1?Test |> should equal "Hi";

这是开源的Apache许可证,您可以查看implementation,它包含单元测试example cases