2010-04-02 9 views
6

Tenir compte de ma première tentative, un type simple F # comme ce qui suit:Comment implémenter correctement une propriété dans 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") 

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 affecté, mon F # Setter est en cours d'exécution, mais le second est assert défaillantes en raison de la valeur sous-jacente de prop ne change pas. Ce genre de sens a du sens pour moi, parce que si je supprime mutable du champ prop, aucune erreur n'est générée (et il faut le faire parce que j'essaie de muter la valeur). Je pense qu'il me manque un concept fondamental.

Quelle est la bonne façon de relier/muter prop dans la classe Test afin que je puisse passer mon test d'unité?

Répondre

8

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 étiez en train de créer une nouvelle liaison (également appelée prop) dans votre setter, donc aucune modification n'était visible.

+0

Merci, @kvb. Rien ne me fait sentir comme un n00b à la langue d'une solution aussi simple que cela. :) –

+0

@Greg - pas de problème. La façon dont les fixations et le travail de duplication peuvent prendre un peu de temps à s'habituer, d'autant plus que d'autres langages font les choses différemment. Cependant, une fois que vous obtenez votre modèle mental droit, je pense que l'élégance de l'approche de F # devient évidente. – kvb

5

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 
9

Comme un côté note, je serais probablement utiliser if .. then au lieu de la match construction car il rend le code plus succinct (correspondant de patterh est particulièrement utile lorsque vous avez besoin pour tester la valeur agains plusieurs modèles complexes). En outre, public est l'accès par défaut pour member, vous pouvez donc faire un peu le code 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") 
+1

J'ai déjà acheté votre livre. :) Lecture utile, bien que j'aurais aimé le garder à portée de main quand j'ai posé cette question! –