Pergunta
Acabei de ler as informações sobre esta página, e enquanto um novo? O operador é mencionado, não está claro para mim o que seria seu uso.
Alguém poderia fornecer uma explicação rápida, postar um código cortado de como esse operador seria usado e possivelmente mencionar um caso de uso?
Editar: Isso é realmente estranho, eu notei que o? O operador não é mais mencionado nas notas de lançamento de Don. Alguma idéia de por que isso?
Solução
Existem dois novos operadores "especiais" nesta versão F#, (?) E (? <-). Eles não são definidos, mas estão disponíveis para sobrecarga, para que você possa defini -los você mesmo. O bit especial é como eles tratam seu segundo operando: eles exigem que ele seja um identificador F# válido, mas passa para a função implementando o operador como uma string. Em outras palavras:
a?b
é dessugarado para:
(?) a "b"
e:
a?b <- c
é dessugarado para:
(?<-) a "b" c
Uma definição muito simples desses operadores pode ser:
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)
Observe que, como o tipo de retorno para o gettor é genérico, você terá que especificá -lo no site de uso na maioria dos casos, ou seja:
let name = foo?Name : string
Embora você ainda possa fazer a corrente (?) (Como o primeiro argumento de (?) Também é genérico):
let len = foo?Name?Length : int
Outra implementação mais interessante é reutilizar o método callbyname fornecido pelo 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
A vantagem disso é que ele lidará com as propriedades e os campos corretamente, trabalhará com os objetos de Idispatch com, etc.
Outras dicas
Parece o "?" O operador está relacionado ao dinâmico Runtime Runtime (DLR). Ou seja, você o usa quando deseja vincular a um membro do objeto (método, propriedade) em tempo de execução, e não no momento da compilação.
É engraçado porque eu esperava que isso fosse como a invocação dinâmica de membros funcionaria em C# também. Infelizmente, C# expõe essa funcionalidade por meio de um tipo "pseudo" ("dinâmico" iirc). Na minha opinião, isso deixa o código um pouco menos claro (porque você precisa rastrear a declaração variável para saber se a chamada é no início ou no final do limite).
Não conheço a sintaxe exata, mas se eu tivesse que adivinhar, ela substitui ou aumenta o "". Operador (DOT). Como em:
let x = foo?Bar()
ou talvez:
let x = foo.?Bar()
There is a module FSharp.Interop.Dynamic, on nuget that implements the dynamic operator using the dlr.
let ex1 = ExpandoObject() in
ex1?Test<-"Hi";
ex1?Test |> should equal "Hi";
It's open source, Apache license, you can look at the implementation and it includes unit test example cases.