Making a field private and exposing it as a Property gives the class power of controlling set and get operations, this can be useful in different scenarios.
Validation
The class can validate provided data before storing it into the field:
class WeatherInfo {
private static readonly int minDegree = -273;
private static readonly int maxDegree = 75;
private int degree;
public int Degree {
get {
return this.degree;
}
set {
if (value < minDegree || value > maxDegree) {
throw new ArgumentOutOfRangeException();
}
}
}
..
..
}
Invalid field value
In some circumstances, a field of an object may not have a meaningful value. Providing a getter method, allows the object to inform it's client about that.
class User {
private DateTime loginTime;
private bool loggedIn;
..
..
public DateTime LoginTime {
get {
if (!this.loggedIn) {
throw new InvalidOperationException();
}
return loginTime;
}
}
}
Not providing a setter, or limiting access to the setter
Another benefit of using properties instead of fields is that it allows the object to limit access to the field. In the previous example we had a method without a setter. Another use of this approach is limiting access to the setter.
class Customer {
private string name;
private string family;
private string nameFamily;
public string name {
get {
return this.name;
}
private set {
if (!string.Equals(name, value)) {
this.name = value;
this.UpdateNameFamily();
}
}
}
private void UpdateNameFamily() {
this.nameFamily = string.Format("{0} {1}", this.name, this.family);
}
..
..
}
as you can see, the benefit of this approach is it allows the class to perform some action when the property gets changed from inside of the class.
Raising events
A common pattern used to raise XXXXChanged events is checking the value in the setter and raise a event if it is changed:
class Question {
public event EventHandler AnsweredChanged;
private bool isAnswered;
..
..
public bool IsAnswered {
get {
return this.isAnswered;
}
set {
if (this.isAnswered != value) {
this.OnIsAnsweredChanged();
}
}
}
private void OnIsAnsweredChanged() {
if (this.AnsweredChanged!= null) {
this.AnsweredChanged(this, EventArgs.Empty);
}
}
}
Another common use of this approach is implementing INotifyPropertyChanged interface.
Logic-less models
Even if you don't need none of what can be achieved by properties, and you have a logic-less class it has been a best practice to not to expose class fields to outside world of the class. In that case, you can simply use auto-properties as the shortcut way to follow the best practice, without directly defining a field.
class UserModel {
public string Username {
get;
set;
}
public DateTime Birthdate {
get;
set;
}
..
..
}