Comment puis-je mettre correctement une propriété en F #?
-
24-09-2019 - |
Question
Considérez ma première tentative, un type simple F # comme suit:
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")
Maintenant, je teste ce via C # (cet objet est exposé à un projet C #, donc apparemment sémantique C # sont souhaitables):
[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 correctement attribué, mon F # Setter est en cours d'exécution, mais le second assert échoue parce que la valeur sous-jacente de prop
ne change pas. Ce genre de fait sens pour moi, parce que si je retire mutable
du champ prop
, aucune erreur est généré (et devrait être parce que je suis en train de muter la valeur). Je pense que je dois manquer un concept fondamental.
Quelle est la bonne façon de rebind / muter prop
dans la classe Test
pour que je puisse passer mon test unitaire?
La solution
Essayez ceci:
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")
Vous devez faire la liaison mutable et modifier sa valeur dans votre setter. Dans votre code initial, vous venez de créer une nouvelle liaison (également appelé prop
) au sein de votre setter, donc aucun changement n'a été visible.
Autres conseils
Comme un côté note, je serais probablement utiliser if .. then
au lieu de construire match
car il rend le code plus succinct (correspondant de patterh est particulièrement utile lorsque vous avez besoin de tester la valeur agains multiples motifs complexes). En outre, public
est l'accès par défaut pour member
, donc vous pouvez rendre le code un peu plus succinct:
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")
Dans votre correspondance de motif vous liez en fait une nouvelle valeur avec
let prop = value
Lorsque vous liez une valeur comme celui-ci avec le même nom, elle masque l'autre valeur pour le champ d'application de la nouvelle qui a été déclaré. Je crois que ce que vous voulez vraiment faire est la suivante:
prop <- value