Когда свойство установлено, должно ли его значение обновляться, даже если оно не изменилось? - PullRequest
2 голосов
/ 09 февраля 2012

Это может быть применено ко многим различным языкам, но я специально работаю с C # и INotifyPropertyChanged.

Если свойство установлено, я должен переназначить его значение, даже если оно не изменилось?Например:

public int IntProperty
...
set
{
    var oldValue = _intProperty;
    _intProperty = value;
    if (!Equals(value, oldValue))
    {
        OnPropertyChanged(...);
    }
}

против

public int IntProperty
...
set
{
    if (!Equals(value, _intProperty))
    {
        _intProperty = value;
        OnPropertyChanged(...);
    }
}

Я просто не могу решить.Технически это не должно иметь значения, но есть некоторые странные угловые случаи (например, странные реализации Equals, которые никогда не должны происходить), которые могут изменить поведение.

Ответы [ 4 ]

2 голосов
/ 09 февраля 2012

На это может влиять тип недвижимости. Некоторые классы имеют интеллектуальные методы Equals, а некоторые нет. Если вы доверяете своему, это не должно иметь значения, но если класс не переопределяет Equals или не делает это хорошо, то это что-то меняет. В целом, я бы сказал, что базовое значение не должно меняться без отправки уведомления, поэтому я бы пошел с # 2.

Для примера, может быть, есть простой держатель данных, который выглядит примерно так:

class Data
{
    public int ID { get; set; }
    public string SomeData { get; set; }
    public string SomeOtherData { get; set; }
    //Assume there are lots of other fields here
    public override bool Equals(object obj)
    {
        Data other = obj as Data;
        if (other != null)
        {
            return ID == other.ID;
        }
        return false;
    }
}

Теперь, если идентификатор равен , предполагается, что уникален (возможно, потому, что он сопоставляется со значением идентификатора БД), тогда это неплохая идея, но это не мешает людям создавать объекты с одинаковым идентификатором и разными значениями данных. Если бы какой-то подлый человек сделал это, вы могли бы в конечном итоге установить значение для свойства, такого как ваше, в котором новое значение действительно существенно отличается, но .Equals скажет, что они одинаковы. Теперь, независимо от того, что здесь происходит, вы несколько облажались, но что еще хуже, не устанавливая значение, которое не должно отличаться, но является (потому что набор находится внутри if), или изменяя значение и не уведомляя подписчиков события о том, что событие изменилось? (У вас также есть третий вариант установки события и уведомления людей, даже если оно изменилось, возможно, указано, что это происходит с помощью аргументов события.) Если подписчик события представляет собой код, который сохраняет изменение в базе данных (которая часто является случай с этим типом структуры), то вы меняете значение в памяти, думая, что оно действительно изменилось (возвращение его является точным эталонным соответствием), но значение по-прежнему не будет сохраняться, потому что событие не было запущено .

Извините за стену текста.

tl; dr версия, пользователи этого кода могут найти способ прокрутить вас независимо от того, что вы делаете; в конечном итоге вам нужно минимальное доверие к ним, чтобы ваш код был эффективным.

1 голос
/ 09 февраля 2012

Если вы собираетесь выполнить проверку в любом случае, я бы сказал, что не стоит беспокоиться об установке значения, если они равны. Спаси себя цикл.

1 голос
/ 09 февраля 2012

Короткий ответ - как правило, либо проверяйте, отличаются ли они, и устанавливайте его только в том случае, если он есть, либо не беспокойтесь о проверке.

Более длинный ответ - для MVVM одной принятой практикой является абстрагирование набора вбазовый класс, где у вас есть две перегрузки функции для установки свойства.Это должно обрабатывать все случаи установки свойства, облегчать их реализацию в ваших унаследованных классах и очищать вещи.

public event PropertyChangedEventHandler PropertyChanged;

public Boolean SetProperty<T>(string propertyName, ref T field, T value, IEqualityComparer<T> comparer)
{
    if (!comparer.Equals(field, value))
    {
        T oldValue = field;
        field = value;

        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

        return true;
    }

    return false;
}

public Boolean SetProperty<T>(string propertyName, ref T field, T value)
{
    return SetProperty(propertyName, ref field, value, EqualityComparer<T>.Default);
}

Затем в вашей ViewModel вы сделаете что-то вроде этого:

private int mMyIntProperty = 0;
public string MyIntProperty
{
    get { return mMyIntProperty; }
    set { SetProperty("MyIntProperty", ref mMyIntProperty, value); }
}

Для простых типов вам не нужно указывать Comparer, так как по умолчанию все будет в порядке.Однако наличие компаратора облегчает проверку сложных типов.

1 голос
/ 09 февраля 2012

Не имеет смысла устанавливать его снова, это только требует времени / экономит производительность.

И поскольку уведомление уже находится внутри оператора if, оно также не содержит больше кода.

...