Я только что прочитал информацию о эта страница, а новая? упоминается оператор, мне совершенно непонятно, как он будет использоваться.
Может ли кто-нибудь дать быстрое объяснение, опубликовать фрагмент кода о том, как будет использоваться этот оператор, и, возможно, упомянуть вариант использования?
< strong> Edit: это действительно неудобно, я заметил, что? Оператор больше не упоминается в примечаниях к выпуску Дона. Есть идеи, почему это так?
Оператор F #?
Ответы (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)
Обратите внимание, что, поскольку тип возвращаемого значения для получателя является общим, в большинстве случаев вам придется указывать его на сайте использования, то есть:
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 и т. Д.
Это похоже на "?" Оператор относится к динамической языковой среде выполнения (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";
Это открытый исходный код, лицензия Apache, вы можете посмотреть реализация и включает примеры примеров модульного тестирования.