设置属性时,即使它没有更改,它的值是否应更新?

时间:2012-02-09 18:03:58

标签: c# inotifypropertychanged

这可以应用于许多不同的语言,但我特别使用C#和INotifyPropertyChanged。

如果设置了属性,即使它没有改变,我应该重新分配它的值吗? 例如:

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

VS

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

我无法决定。从技术上讲,它不应该有所作为,但有一些奇怪的极端情况(如不应该发生的奇怪的Equals实现)可能会改变行为。

4 个答案:

答案 0 :(得分:2)

这可能受到财产类型的影响。有些类有智能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;
    }
}

现在,如果ID 假设是唯一的(可能因为它映射到数据库ID值),那么这不是一个想法,但它不会阻止人们四处走动创建具有相同ID和不同数据值的对象。如果某些卑鄙的人这样做,你最终可能会为某个属性设置一个值,例如你的新值确实显着不同,但是.Equals会说它们是相同的。现在无论发生什么事,你都有点搞砸了,但更糟糕的是,没有设置一个不应该不同的值,而是(因为集合在if中)或者更改了值而没有通知事件订阅者该事件改变了吗? (您还有第三个选项来设置事件并通知人们即使它发生了变化,也可能表明这是通过事件args的情况。)如果事件订阅者是持续更改数据库的代码(通常是这种类型的结构的情况)那么你正在改变一个内存中的值,认为它确实改变了(让它退出是一个精确的参考匹配),但该值仍然不会被持久化,因为事件没有被触发

对不起文字墙。

tl; dr版本,无论你做什么,这段代码的用户都可以找到一种方法来搞砸你;最终,您需要对它们的最小信任才能使您的代码生效。

答案 1 :(得分:1)

再次设置它是没有用的,只需要时间/节省性能。

由于通知已经在if语句中,因此它也不再是代码。

答案 2 :(得分:1)

如果您打算以任何一种方式进行检查,那么我会说如果它们相等则不要担心设置值。节省自己的周期。

答案 3 :(得分:1)

简短回答 - 一般来说,要么检查它们是否不同,只有在它是,或者不打扰检查时才设置它。

更长的答案 - 对于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,因为默认情况下会很好。但是,使用比较器可以更轻松地检查复杂类型。