Guidelines for Properties in C#: Property vs Field
October 7th, 2009This post is a summary of guidelines and rules for choosing between Property and Field in C# language. In general fields - should be used to store internal state of an object and should not be public. You will never (except maybe few exceptions) find public fields in base .NET class library.
On the contrary Property should expose distinguishing feature of an object either public or protected. There should not be much use of the private properties as they are points of confusion with a fields.
Property not always represents storage of data values - it may be evaluated at accessing. That is why property might expose side-effect which will never happen while using fields, for example, consider following code snippet:
MyClass o = new MyClass();
o.Property = “Hello”;
return o.Property == “Hello”;
One would expect this to return true, but as seen from example it would not be always the case. Consider this:
string Property
{
get { return string.Empty; }
set { }}
Ideally following rule should be considered while designing public property: immediate access to the property getter after setting some value should return this value.
Often properties are used to implement change notification via INotifyPropertyChanged interface and I would recommend to follow such pattern initially described to me by Denis Vuyka (notice how property name passed to OnPropertyChanged handler, thus in future it will ease maintaining code during property renaming) :
public class MyClass : INotifyPropertyChanged
{
private string message;
public string Message
{
get
{
return message;
}
set
{
if (object.Equals(message, value)) return;
message = value;
OnPropertyChanged(() => this.Message);
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void
OnPropertyChanged(
Expression<Func<object>> propertyFunc)
{
if (PropertyChanged != null)
PropertyChanged.Invoke(this, new
PropertyChangedEventArgs(
((MemberExpression)propertyFunc.Body)
.Member.Name));
}
#endregion
}
Another common side effect which might be exposed by property - is a modification of the object’s state during getting value:
public class Wrong
{
string newText = null;
public string Text
{
get
{
if (newText == null)
newText = GetTextConstant();
return newText;
}
….
}
}
This behaviour may lead to unexpected results. Consider example of WinForm multi-threaded application whereas background thread access objects in Read-Only manner, i.e. it uses only property getters. UI in main thread subscribes to all objects changes for updating. Now, if getter in background thread will cause change in state of the instance, it will raise change event. UI update handler will be invoked in background thread which may lead to application crash.
So, now we are ready to formulate another fundamental rule: accessing property getter should never lead to object’s state change.
