Come faccio correttamente implementare una proprietà in F #?
-
24-09-2019 - |
Domanda
Si consideri il mio primo tentativo, un tipo semplice in F # come il seguente:
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")
Ora provare questa via C # (questo oggetto è stato esposto ad un progetto C #, in modo apparente C # semantica è auspicabile):
[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
sia correttamente assegnato, la mia F # Setter è in esecuzione, ma la seconda asserzione non riesce perché il valore sottostante di prop
non viene modificato. Questa sorta di senso per me, perché se tolgo mutable
dal campo prop
, viene generato alcun errore (e uno dovrebbe essere perché sto cercando di mutare il valore). Penso Devo mancare un concetto fondamentale.
Qual è il modo corretto per rilegare / prop
mutare nella classe Test
in modo che posso passare il mio test di unità?
Soluzione
Prova questo:
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")
È necessario fare il mutabile vincolante e quindi modificare il suo valore nella vostra setter. Nel codice iniziale, stavi solo creando un nuovo vincolante (chiamato anche prop
) all'interno del tuo setter, quindi nessun cambiamento era visibile.
Altri suggerimenti
Come un lato nota, avrei probabilmente usare if .. then
al posto del costrutto match
in quanto rende il codice più succinta (patterh corrispondenza è particolarmente utile quando si ha bisogno di testare i agains di valore molteplici modelli complessi). Inoltre, public
è l'accesso di default per member
, in modo da poter rendere il codice un po 'più succinta:
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")
Nel vostro pattern match in realtà si sta legando un nuovo valore con
let prop = value
Quando si associa un valore come questo con lo stesso nome, verrà ombra l'altro valore per il campo di applicazione della nuova dichiarato uno. Credo che ciò che si vuole realmente fare è questo:
prop <- value