2010-04-02 20 views
6

considero il mio primo tentativo, un tipo semplice in F # come il seguente:Come implementare correttamente una proprietà in F #?

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 testare 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 venga assegnato, la mia F # Setter è in esecuzione, ma la seconda asserzione non riesce a causa del valore sottostante di prop non viene modificato. Questo tipo di ha senso per me, perché se rimuovo mutable dal campo prop, non viene generato alcun errore (e uno dovrebbe essere perché sto cercando di mutare il valore). Penso che mi debba mancare un concetto fondamentale.

Qual è il modo corretto di riassociare/mutare prop nella classe Test in modo che possa superare il test dell'unità?

risposta

8

Prova questa:

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") 

Hai bisogno di fare il mutabile vincolante e quindi modificare il suo valore nella vostra setter. Nel tuo codice iniziale, stavi creando una nuova associazione (chiamata anche prop) all'interno del tuo setter, quindi nessuna modifica era visibile.

+0

Grazie, @kvb. Niente mi fa sentire come un n00b nella lingua piuttosto che una soluzione tanto semplice. :) –

+0

@Greg - nessun problema. Il modo in cui i binding e gli shadowing possono richiedere un po 'di tempo per abituarsi, in particolare perché le altre lingue fanno le cose in modo così diverso. Tuttavia, una volta ottenuto il modello mentale, penso che l'eleganza dell'approccio di F # sia evidente. – kvb

5

Nel vostro pattern match si sono effettivamente vincolanti 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 dichiarata. Credo che ciò che si vuole realmente fare è questo:

prop <- value 
9

Come un lato nota, probabilmente uso if .. then al posto del match costrutto in quanto rende il codice più succinta (patterh corrispondenza è particolarmente utile quando è necessario per testare il valore contro più schemi complessi). Inoltre, public è l'accesso predefinito 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") 
+1

Ho già comprato il tuo libro. :) Lettura utile, anche se mi piacerebbe averlo tenuto a portata di mano quando ho fatto questa domanda! –

Problemi correlati