Ответ 1
В этой выпуске 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
Еще одна, более интересная, реализация заключается в повторном использовании метода CallByName, предоставляемого VB:
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
Преимущество состоит в том, что он правильно обрабатывает как свойства, так и поля, работает с COM-объектами IDispatch и т.д.