How do I properly implement a property in F#?
Consider my first attempt, a simple type in F# like the following:
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")
Now I test this via C# (this object is being exposed to a C# project, so apparent C# semantics are desirable):
[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
is properly assigned, my F# Setter is running, but the second assert is failing because the underlying value of prop
isn't changed. This sort of makes sense to me, because if I remove mutable
from the prop
field, no error is generated (and one should be because I'm trying to mutate the value). I think I must be missing a fundamental concept.
What's the correct way to rebind/m开发者_开发问答utate prop
in the Test
class so that I can pass my unit test?
As a side-note, I would probably use if .. then
instead of the match
construct as it makes the code more succinct (patterh matching is especially valuable when you need to test the value agains multiple complex patterns). Also, public
is the default access for member
, so you can make the code a bit more 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")
Try this:
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")
You need to make the binding mutable and then alter its value in your setter. In your initial code, you were just creating a new binding (also called prop
) within your setter, so no change was visible.
In your pattern match you are actually binding a new value with
let prop = value
When you bind a value like this with the same name, it will shadow the other value for the scope of the newly declared one. I believe what you actually want to do is this:
prop <- value
精彩评论