15

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

4

3 回答 3

31

此 F# 版本中有两个新的“特殊”运算符,(?) 和 (?<-)。它们没有定义,但它们可用于重载,因此您可以自己定义它们。特殊的一点是他们如何对待他们的第二个操作数:他们要求它是一个有效的 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 对象等。

于 2009-05-22T23:34:25.803 回答
4

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

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

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

let x = foo?Bar()

或许:

let x = foo.?Bar()
于 2009-05-21T00:04:43.227 回答
1

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

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

它是开源的,Apache 许可证,您可以查看实现,它包括单元测试示例案例

于 2011-07-29T12:42:42.090 回答