Como faço para implementar corretamente uma propriedade em f#?
-
24-09-2019 - |
Pergunta
Considere minha primeira tentativa, um tipo simples em F# como o seguinte:
type Test() =
inherit BaseImplementingNotifyPropertyChangedViaOnPropertyChanged()
let mutable prop: string = null
member this.Prop
with public get() = prop
and public set value =
match value with
| _ when value = prop -> ()
| _ ->
let prop = value
this.OnPropertyChanged("Prop")
Agora eu testo isso via C# (este objeto está sendo exposto a um projeto C#, portanto, a semântica aparente C# é desejável):
[TestMethod]
public void TaskMaster_Test()
{
var target = new FTest();
string propName = null;
target.PropertyChanged += (s, a) => propName = a.PropertyName;
target.Prop = "newString";
Assert.AreEqual("Prop", propName);
Assert.AreEqual("newString", target.Prop);
return;
}
propName
está atribuído corretamente, meu fetter F# está em execução, mas a segunda afirmação está falhando porque o valor subjacente de prop
não é alterado. Este tipo de sentido para mim, porque se eu remover mutable
de prop
Campo, nenhum erro é gerado (e um deve ser porque estou tentando mudar o valor). Eu acho que devo estar perdendo um conceito fundamental.
Qual é a maneira correta de se rebenar/muta prop
no Test
aula para que eu possa passar no meu teste de unidade?
Solução
Experimente isso:
type Test() =
inherit BaseImplementingNotifyPropertyChangedViaOnPropertyChanged()
let mutable prop: string = null
member this.Prop
with public get() = prop
and public set value =
match value with
| _ when value = prop -> ()
| _ ->
prop <- value
this.OnPropertyChanged("Prop")
Você precisa tornar a ligação mutável e alterar seu valor no seu setter. No seu código inicial, você estava apenas criando uma nova ligação (também chamada prop
) dentro do seu setter, então nenhuma alteração foi visível.
Outras dicas
Como uma nota lateral, eu provavelmente usaria if .. then
ao invés de match
Construa, pois torna o código mais sucinto (a correspondência Patterh é especialmente valiosa quando você precisa testar o valor novamente vários padrões complexos). Também, public
é o acesso padrão para member
, para que você possa tornar o código um pouco mais sucinto:
type Test() =
inherit BaseImplementingNotifyPropertyChangedViaOnPropertyChanged()
let mutable prop : string = null
member this.Prop
with get() = prop
and set(value) =
if value <> prop then
prop <- value
this.OnPropertyChanged("Prop")
Na sua correspondência de padrão, você está realmente vinculando um novo valor com
let prop = value
Quando você vincula um valor como esse com o mesmo nome, ele sombreará o outro valor para o escopo do recém -declarado. Eu acredito que o que você realmente quer fazer é o seguinte:
prop <- value