Brajesh
Brajesh

Reputation: 115

C# Fastest way to know something in object has changed?

I want to know, if the value of any of the private or public fields has changed. Is there any way other than over-riding GetHashCode() or calculating CRC?

The algorithm should be fast too.

Upvotes: 8

Views: 8711

Answers (4)

elCairo
elCairo

Reputation: 81

Insert in every public setter a boolean value, like m_IsChanged, then using a public getter only to check if one of the properties has been changed.

Example:

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; }
} 

Upvotes: 1

Dan Bryant
Dan Bryant

Reputation: 27505

If it needs to work for any type and needs to detect any modification, with no false negatives or false positives, I don't see any better way than a copy of all field values for reference. Since you need it to be fast, I would recommend the following:

  1. Write a routine that uses reflection to perform a shallow copy of all field values.

  2. Write a routine that compares the fields by value (if you're looking for changes in nested structures, like arrays or collections, your problem is much tougher.)

  3. Once the above work, you can use IL Emit and write code that does the Reflection once and emits code for the shallow-copy and comparison operations. Now you have some DynamicMethod instances you can use for each operation. These are quite fast, once emitted and jitted.

Upvotes: 2

devuxer
devuxer

Reputation: 42374

Normally, this would be done with the INotifyPropertyChanged interface (link). It is really only practical to use it with properties, though, not fields. However, you could create a private property for each of your private fields. Once you have everything as a property, edit the setter so that you check if the value has changed, then call NotifyPropertyChanged() if it has.

Example:

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));
    }
}

Upvotes: 5

Daniel Mošmondor
Daniel Mošmondor

Reputation: 19956

You may want to encapsulate all your data (which you want to monitor for change) inside the get/set accessors (a.k.a. properties).

Then, in set accessor, check if value has changed, set it to new value, and:

  • set _dirty to true (if you need to check it later)

or

  • raise some event to your liking

Some notes on CRC - even if you have non-colliding CRC/HASH algoritam for your object, you must have original hash somewhere. But simple hashes are likely to duplicate, so you again have speed issue.

Upvotes: 2

Related Questions