Я только что прочитал информацию о этой странице, а в то время как новый? оператор упоминается, это совершенно неясно, каково было бы его использование.
Может ли кто-нибудь, пожалуйста, дать краткое объяснение, опубликовать код, который был бы отключен от того, как этот оператор будет использоваться и, возможно, упомянуть прецедент?
Изменить: это действительно неудобно, я заметил, что? оператор больше не упоминается в примечаниях к выпуску Don. Любая идея о том, почему?
F # operator "?"
Ответ 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 и т.д.
Ответ 2
Звучит как "?" оператор относится к динамическому языку Runtime (DLR). То есть вы используете его, когда хотите привязываться к члену объекта (метод, свойство) во время выполнения, а не во время компиляции.
Это смешно, потому что я надеялся, что так будет работать динамический вызов членов на С#. Увы, С# предоставляет эту функциональность с помощью псевдо-типа ( "динамический" IIRC). На мой взгляд, это делает код несколько менее понятным (потому что вам нужно отследить объявление переменной, чтобы узнать, связан ли вызов с ранней привязкой или поздней привязкой).
Я не знаю точного синтаксиса, но если бы я должен был догадаться, он либо заменяет, либо увеличивает ".". (точка). Как в:
let x = foo?Bar()
или возможно:
let x = foo.?Bar()
Ответ 3
Существует модуль FSharp.Interop.Dynamic, на nuget, который реализует динамический оператор, используя dlr.
let ex1 = ExpandoObject() in
ex1?Test<-"Hi";
ex1?Test |> should equal "Hi";
Это открытый исходный код, лицензия Apache, вы можете посмотреть реализацию и включить unit test примеры случаев.