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

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.

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

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.

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:
Write a routine that uses reflection to perform a shallow copy of all field values.
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.)
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.

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

Related

Property Getters and Setters when implementing INotifyPropertyChanged?

I am trying to implement INotifyPropertyChanged for a lot of classes, and each of these classes have lots and lots of properties. I have been following this MSDN documentation for how to implement INofifyPropertyChanged, but their instructions don't seem to be practical in cases where a class has many many properties.
Currently most of my properties use the short hand:
public DateTime? DateClosed { get; set; }
But the documentation says that i need to add the following to each setter method:
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("DateClosed");
This means that I then need to declare a body for the get method and declare private variables to handle the actual getting and setting of properties. Like this:
private DateTime? _dateOfIncident = null;
public DateTime? DateClosed
{
get { return _dateOfIncident; }
set
{
_dateOfIncident= value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("DateClosed");
}
}
Does anyone know a way around this?
A few classes can easily be changed to implement INotifyPropertyChanged. But since you state you have a lot of classes with a lot of properties, it's a real burden to get this done manually or even with templates.
What you really need is a tool that does it for you, so I present you Fody and it's NotifyPropertyChanged plugin. What Fody does is weave some extra code in between your code at compile time. The only thing you have to do is add a single attribute on the classes you want to implement INotifyPropertyChanged and the rest is done for you.
[ImplementPropertyChanged]
public class Person
{
public string GivenNames { get; set; }
public string FamilyName { get; set; }
public string FullName
{
get
{
return string.Format("{0} {1}", GivenNames, FamilyName);
}
}
}
I'm not sure you're going to find a workaround here. Auto-properties, as you're using them now, are really just a compiler shorthand that get's converted to full properties with a backing field eventually anyway (at least, as I understand it).
The use of INPC is a routine that's sorta separate and apart from the duty of a normal property. It's notifying subscribers (usually, your view XAML) that the property in question has changed or is changing.
tl;dr -- you're not going to get around having to rewrite autoproperties to full properties with backing fields. But toolkits like MVVMLight have some great Visual Studio code snippets to make this relatively fast. Eventually you can even do this:
private string _someString;
public string SomeString
{
get { return _someString;}
set
{
//Set returns bool, so you can trigger other logic on it!
Set(() => SomeString, ref _someString, value);
}
}
This gives you some neat features:
Strong naming (unlike the magic string in your example)
Set only triggers INPC event if the value is different
Set returns boolean so you can perform more action if the value changed
MVVMLight is nice in that you don't have to use all its features, or even implement MVVM pattern. It just has a lot of nice 'tools' you can leverage.
There are a lot of patterns to do it, or you can buy a tool like PostSharp that will do it for you.
For example, here is one method of doing it:
public abstract class BaseNotifyPropertyChanged : INotifyPropertyChanged
{
private Dictionary<string, object> _valueStore = new Dictionary<string, object>();
public event PropertyChangedEventHandler PropertyChanged;
protected T Get<T>([CallerMemberName]string property = null)
{
object value = null;
if (!_valueStore.TryGetValue(property, out value))
return default(T);
return (T)value;
}
protected void Set<T>(T value, [CallerMemberName]string property = null)
{
_valueStore[property] = value;
OnPropertyChangedInternal(property);
}
protected void OnPropertyChanged([CallerMemberName]string property = null)
{
OnPropertyChangedInternal(property);
}
private void OnPropertyChangedInternal(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Which you then inherit from your classes:
public class PlainOldObject : BaseNotifyPropertyChanged
{
public int MyProperty
{
get { return Get<int>(); }
set { Set(value); }
}
}
Which takes care of the backing store and everything for you. You may want to add logic to only call the OnPropertyChangedInternal if the property actually changed (compare references or value), but I'll leave that as an exercise for you.
Simply use the Observable Object class. Instead of creating a DateTime property, you'd create an ObservableObject<DateTime> and you would just bind to DateClosed.Value.

When to use the public or private property?

If I have a class like so:
public class MyClass:INotifyPropertyChanged
{
private Visibility isVisible;
private ObservableCollection<string> names;
public Visibility IsVisible
{
get{ return isVisible;}
set { isVisible = value; OnPropertyChanged("IsVisible");}
}
public ObservableCollection<string> Names
{
get { return names;}
set { names = value; OnPropertyChanged("Names");}
}
//ctor
public MyClass(){
names = new ObservableCollection<string>();
}
//INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Before any one beheads me - I have done quite a bit of looking up and have found a mixed bag of answers...
Do I modify the public or private properties/variables for use in my bindings? i.e. I have an issue where adding to names collection will trigger OnPropertyChanged and changing isVisible will NOT trigger OnPropertyChanged. My assumption is that this is because names is an ObservableCollection where as isVisible is not but I am not sure...
If I am supposed to uses the public properties - what is the need for having the private ones?
You don't need a private property, only a private field would be enough so replace:
private Visibility isVisible {get; set;}
with
private Visibility isVisible;
If I am supposed to uses the public properties - what is the need for
having the private ones?
You cannot use Auto-properties with INotifyPropertyChanged. That is why you need a backing field for your property IsVisible.
See: An elegant way to implement INotifyPropertyChanged
So I think you are confusing Properties and Fields (aka variables).
public class Example()
{
public int FieldExample;
private int _propertyExample;
public int PropertyExample
{
get
{
return _propertyExample;
}
set
{
_propertyExample = value;
}
}
}
In simple usage scenarios, the difference between a field and a property isn't obvious. But properties have different plumbing under the hood that allows them to take advantage of reflection and binding. For WPF, this means you've got to have public properties. Best practice for a Public Property is associate it with a private (or protected) field - and that field name is usually either prefixed with an _ and/or starts with lower case character. This is called a "backing field."
The private backing field holds the actual data, the public property is just the means by which other classes can interact with that data. Inside the get and set blocks, you can place any code you want: instead of returning my backing field, I could instead put: return 5;. It's not useful, and it's poor practice, but I can. Generally, the code that resides in your get and set blocks should still set or get the value; although you might validate the input first, and/or format it first. The pattern you are implementing in your sets for WPF raises an event that the property has changed. Other parts of your program are listening for that event so they know to update the UI.
So in your code, if you only change the backing field and don't raise an event that there has been a change, the UI will not update. You might desire this behavior if you are performing a complex action on an object, and want to hold off performing an UI update until a complete batch of items are finished, but that's an optimization and for starters you are probably better off always accessing/setting to the Public Property.

Create an event to watch for a change of variable

Let's just say that I have:
public Boolean booleanValue;
public bool someMethod(string value)
{
// Do some work in here.
return booleanValue = true;
}
How can I create an event handler that fires up when the booleanValue has changed? Is it possible?
Avoid using public fields as a rule in general. Try to keep them private as much as you can. Then, you can use a wrapper property firing your event. See the example:
class Foo
{
Boolean _booleanValue;
public bool BooleanValue
{
get { return _booleanValue; }
set
{
_booleanValue = value;
if (ValueChanged != null) ValueChanged(value);
}
}
public event ValueChangedEventHandler ValueChanged;
}
delegate void ValueChangedEventHandler(bool value);
That is one simple, "native" way to achieve what you need. There are other ways, even offered by the .NET Framework, but the above approach is just an example.
INotifyPropertyChanged is already defined to notify if property is changed.
Wrap your variable in property and use INotifyPropertyChanged interface.
Change the access of the BooleanValue to private and only allow changing it through one method for consistency.
Fire your custom event in that method
.
private bool _boolValue;
public void ChangeValue(bool value)
{
_boolValue = value;
// Fire your event here
}
Option 2: Make it a property and fire the event in the setter
public bool BoolValue { get { ... } set { _boolValue = value; //Fire Event } }
Edit: As others have said INotifyPropertyChanged is the .NET standard way to do this.
Perhaps take a look at the INotifyPropertyChanged interface. You're bound to come across it's use again in future:
MSDN: http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
CallingClass.BoolChangeEvent += new Action<bool>(AddressOfFunction);
In your class with the bool property procedure:
public event Action<bool> BoolChangeEvent;
public Boolean booleanValue;
public bool someMethod(string value)
{
// Raise event to signify the bool value has been set.
BoolChangeEvent(value);
// Do some work in here.
booleanValue = true;
return booleanValue;
}
No it is not possible* to get notified about for changes in value of a variable.
You can achieve almost what you want by making the value to be a property of some class and fire events on change as you wish.
*) if your code is debugger for a process you can make CPU to notify you about changes - see data chage breakpoints in Visual Studio. This will require at least some amount of native code and harder to implement correctly for manged code due to hance of objects to be moved in memory by GC.

c# bool.change event

Can I setup an event listener so that when a bool changes a function is called?
You should use properties in C#, then you can add any handling you want in the setter (logging, triggering an event, ...)
private Boolean _boolValue
public Boolean BoolValue
{
get { return _boolValue; }
set
{
_boolValue = value;
// trigger event (you could even compare the new value to
// the old one and trigger it when the value really changed)
}
}
Manually, Yes you can
public delegate void SomeBoolChangedEvent();
public event SomeBoolChangedEvent SomeBoolChanged;
private bool someBool;
public bool SomeBool
{
get
{
return someBool;
}
set
{
someBool = value;
if (SomeBoolChanged != null)
{
SomeBoolChanged();
}
}
}
Not sure however if this is what you are looking for.
The important question here is: when a bool what changes?
Since bool is a value type you cannot pass around references to it directly. So it doesn't make sense to talk about anything like a Changed event on bool itself -- if a bool changes, it is replaced by another bool, not modified.
The picture changes if we 're talking about a bool field or property on a reference type. In this case, the accepted practice is to expose the bool as a property (public fields are frowned upon) and use the INotifyPropertyChanged.PropertyChanged event to raise the "changed" notification.
Look into implementing INotifyPropertyChanged. MSDN has got a great How To on the subject

Is there a way to find out if a property or variable has been set?

As per title, can I find out the history of a property or variable, in terms of whether it has been set or not?
Reason for this is I have some query classes, any properties that have not been set should not be included in the generated query.
Currently I am just trying to add a PropertyInfo instance (I need the name of the property, this is vital to the query generation due to mappings) to a list of properties which have been set in set{}. This is ugly though as it requires more code for what should be classes that only contain properties and no logic (i.e. no removal of stufffrom a list).
Is there something built-in I can use or a more elegant method?
Assuming you're talking about dynamic entities, you could check for null using reflection but this won't tell you anything if the original value was null (or zero in case of numeric data-types).
But best way is to make it implement INotifyPropertyChanged and have a list of properties that have been materialized.
public class Item : INotifyPropertyChanged
{
private List<string> _MaterializedPropertiesInternal;
private List<string> MaterializedPropertiesInternal
{
get
{
if (_MaterializedPropertiesInternal==null)
_MaterializedPropertiesInternal = new List<string>();
return _MaterializedPropertiesInternal;
}
}
private ReadOnlyCollection<string> _MaterializedProperties;
public IEnumerable<string> MaterializedProperties
{
get
{
if (_MaterializedProperties==null) _MaterializedProperties =
new ReadOnlyCollection<string>(MaterializedPropertiesInternal);
return _MaterializedProperties;
}
}
private int _MyProperty;
public int MyProperty
{
get { return _MyProperty; }
set
{
_MyProperty = value;
OnPropertyChanged("MyProperty");
}
}
protected void OnPropertyChanged(string propertyName)
{
if(PropertyChanged != null) PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
MaterializedPropertiesInternal.Add(propertyName);
}
public event PropertyChangedEventHandler PropertyChanged;
}
Make the properties nullable, e.g. of type int? instead of type int, so that their value is null if they haven't been set.

Categories

Resources