2010-04-02 21 views
6

considerar mi primer intento, un tipo simple en F # como el siguiente:¿Cómo implemento correctamente una propiedad en 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") 

Ahora probar esta vía C# (este objeto está siendo expuesto a un proyecto de C#, así aparentes C# semántica son deseables):

[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á asignado correctamente, mi F # Setter está en marcha, pero la segunda aserción está fallando debido a que el valor subyacente de prop no se cambia. Esto tiene sentido para mí, porque si elimino mutable del campo prop, no se genera ningún error (y uno debe ser porque estoy tratando de modificar el valor). Creo que me falta un concepto fundamental.

¿Cuál es la forma correcta de volver a vincular/mutar prop en la clase Test para que pueda pasar la prueba de mi unidad?

Respuesta

8

Prueba esto:

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

Usted necesita hacer la unión mutable y luego alterar su valor en su colocador. En su código inicial, solo estaba creando un nuevo enlace (también llamado prop) dentro de su setter, por lo que no se veía ningún cambio.

+0

Gracias, @kvb. Nada me hace sentir como un n00b en el lenguaje de una solución tan simple como eso. :) –

+0

@Greg - no hay problema. La forma en que funcionan las encuadernaciones y el sombreado puede llevar un tiempo acostumbrarse, especialmente porque otros lenguajes hacen las cosas de manera tan diferente. Sin embargo, una vez que obtenga su modelo mental correctamente, creo que la elegancia del enfoque de F # se hace evidente. – kvb

5

En el ajuste de patrones en realidad se está atando un nuevo valor con

let prop = value 

Al enlazar un valor de este tipo con el mismo nombre, que ocultará el otro valor para el ámbito de la recién declarada uno. Creo que lo que realmente quiere hacer es lo siguiente:

prop <- value 
9

Como nota lateral, que probablemente utilice if .. then en lugar de la match construcción ya que hace que el código sea más sucinta (coincidente patterh es especialmente valiosa cuando se necesita para probar el valor contra múltiples patrones complejos). Además, public es el acceso predeterminado para member, por lo que puede hacer que el código un poco más sucinta:

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

Ya compré tu libro por completo. :) ¡Lectura útil, aunque me gustaría haberlo tenido a mano cuando hice esta pregunta! –

Cuestiones relacionadas