【发布时间】:2010-10-27 19:24:17
【问题描述】:
我刚刚阅读了this page 上的信息,而一个新的?提到了运营商,我不清楚它的用途是什么。
谁能提供一个快速的解释,发布一个如何使用这个运算符的代码,并可能提到一个用例?
编辑:这真的很尴尬,我注意到 ?操作员在 Don 的发行说明中不再提及。知道这是为什么吗?
【问题讨论】:
标签: visual-studio-2010 f#
我刚刚阅读了this page 上的信息,而一个新的?提到了运营商,我不清楚它的用途是什么。
谁能提供一个快速的解释,发布一个如何使用这个运算符的代码,并可能提到一个用例?
编辑:这真的很尴尬,我注意到 ?操作员在 Don 的发行说明中不再提及。知道这是为什么吗?
【问题讨论】:
标签: visual-studio-2010 f#
在 nuget 上有一个模块 FSharp.Interop.Dynamic,它使用 dlr 实现动态运算符。
let ex1 = ExpandoObject() in
ex1?Test<-"Hi";
ex1?Test |> should equal "Hi";
它是开源的,Apache许可证,你可以看看implementation,它包括单元测试example cases。
【讨论】:
在这个 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 对象等。
【讨论】:
听起来像“?”运算符与动态语言运行时 (DLR) 相关。也就是说,当您想在运行时而不是在编译时绑定到对象成员(方法、属性)时使用它。
这很有趣,因为我希望这也是动态成员调用在 C# 中的工作方式。唉,C# 通过“伪”类型(“动态”IIRC)公开了这个功能。在我看来,这会使代码不太清晰(因为您必须跟踪变量声明才能知道调用是早期绑定还是后期绑定)。
我不知道确切的语法,但如果我不得不猜测,它会替换或增加“。” (点)运算符。如:
let x = foo?Bar()
或者也许:
let x = foo.?Bar()
【讨论】: