Как правильно реализовать свойство в F #? - PullRequest
6 голосов
/ 02 апреля 2010

Рассмотрим мою первую попытку, простой тип на 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")

Теперь я проверяю это через C # (этот объект открыт для проекта C #, поэтому очевидна семантика C #):

[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 назначен правильно, мой F # Setter работает, но второе утверждение не выполняется, поскольку базовое значение prop не изменилось. Это имеет смысл для меня, потому что, если я удаляю mutable из поля prop, ошибка не генерируется (и это должно быть, потому что я пытаюсь изменить значение). Я думаю, что мне не хватает фундаментальной концепции.

Как правильно перевязать / изменить prop в классе Test, чтобы я мог пройти мой модульный тест?

Ответы [ 3 ]

9 голосов
/ 02 апреля 2010

В качестве дополнительного примечания, я бы, вероятно, использовал бы if .. then вместо конструкции match, так как это делает код более лаконичным (сопоставление с шаблоном особенно полезно, когда вам нужно протестировать значение с помощью нескольких сложных шаблонов). Кроме того, public является доступом по умолчанию для member, так что вы можете сделать код более кратким:

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") 
8 голосов
/ 02 апреля 2010

Попробуйте это:

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

Вам нужно сделать привязку изменчивой, а затем изменить ее значение в вашем установщике. В своем исходном коде вы просто создавали новую привязку (также называемую prop) внутри вашего установщика, поэтому никаких изменений не было видно.

5 голосов
/ 02 апреля 2010

В вашем сопоставлении с образцом вы фактически связываете новое значение с

let prop = value

Когда вы связываете подобное значение с тем же именем, оно скрывает другое значение для области действия вновь объявленного. Я верю, что вы действительно хотите сделать это:

prop <- value
...