我刚刚看了这个页面上的信息,又是新的吗?提到了运营商,我不清楚它的用途是什么。
任何人都可以提供一个快速的解释,发布一个如何使用这个操作符的代码,并可能提到一个用例吗?
编辑:这真的很尴尬,我注意到 ? 操作员在 Don 的发行说明中不再提及。知道为什么吗?
3 回答
此 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 对象等。
听起来像“?” 运算符与动态语言运行时 (DLR) 相关。也就是说,当您想在运行时而不是在编译时绑定到对象成员(方法、属性)时使用它。
这很有趣,因为我希望这也是动态成员调用在 C# 中的工作方式。唉,C# 通过“伪”类型(“动态”IIRC)公开了这个功能。在我看来,这会使代码不太清晰(因为您必须跟踪变量声明以了解调用是早期绑定还是后期绑定)。
我不知道确切的语法,但如果我不得不猜测,它会替换或增加“。” (点)运算符。如:
let x = foo?Bar()
或许:
let x = foo.?Bar()
nuget 上有一个模块FSharp.Interop.Dynamic,它使用 dlr 实现动态运算符。
let ex1 = ExpandoObject() in
ex1?Test<-"Hi";
ex1?Test |> should equal "Hi";