我想知道,如果任何私有或公共字段的值发生了变化。 除了覆盖GetHashCode()或计算CRC之外还有其他方法吗?
算法也应该很快。
-Thanks,
-Brajesh
答案 0 :(得分:5)
通常,这将使用INotifyPropertyChanged
接口(link)完成。实际上,将它与属性一起使用是非常实际的,而不是字段。但是,您可以为每个私有字段创建一个私有属性。将所有内容作为属性后,编辑setter以检查值是否已更改,然后调用NotifyPropertyChanged()
(如果有)。
示例:
public event PropertyChangedEventHandler PropertyChanged;
private int _foo;
public int Foo
{
get { return _foo; }
set
{
if (_foo != value)
{
_foo = value;
NotifyPropertyChanged("Foo");
}
}
}
private void NotifyPropertyChanged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
答案 1 :(得分:2)
您可能希望在get / set访问器(a.k.a. properties)中封装所有数据(要监视更改)。
然后,在set accessor中,检查值是否已更改,将其设置为新值,然后:
或
关于CRC的一些注意事项 - 即使你的对象有非碰撞的CRC / HASH算法,你必须在某个地方有原始的哈希值。但是简单的哈希可能会重复,所以你再次遇到速度问题。
答案 2 :(得分:1)
如果它需要适用于任何类型并且需要检测任何修改,没有错误否定或误报,我没有看到比所有字段值的副本更好的方法以供参考。由于您需要快速,我建议如下:
编写一个使用反射执行所有字段值的浅表副本的例程。
编写一个按值比较字段的例程(如果您正在寻找嵌套结构中的更改,例如数组或集合,那么您的问题就更难了。)
完成上述工作后,您可以使用IL Emit编写一次执行Reflection的代码,并为浅拷贝和比较操作发出代码。现在,您可以使用一些DynamicMethod实例来执行每个操作。这些都非常快,一旦发射和发射。
答案 3 :(得分:1)
在每个公共setter中插入一个布尔值,如m_IsChanged,然后仅使用公共getter检查其中一个属性是否已更改。
示例:
private bool m_IsChanged = false;
private double m_DoubleValue;
//[...] all other private properties
public double DoubleValue
{
get { return m_DoubleValue; }
set
{
if(m_DoubleValue != value)
m_IsChanged = true;
m_DoubleValue = value;
}
}
//[...] all other getters/setters
public bool IsChanged
{
get { return m_IsChanged; }
}