Article
Object Oriented C# for ASP.NET Developers
C# Properties
Previously, we modified the PickNut method so that it would not accept too high a number, which would cause our CoconutTree to think it contained a negative number of coconuts. But there is a much simpler way to produce this unrealistic situation:
CoconutTree ct = new CoconutTree();
ct.numNuts = -10;
How can we protect object fields like numNuts from being assigned values like this that don't make sense? The solution is to make the fields themselves private, and permit access to them using a C# Property.
A C# Property is a pair of methods that is used to read and write a property of an object. From here on, C# Properties will be called simply properties.
Here is an updated version of our CoconutTree class that makes use of this technique:
1 public class CoconutTree : Tree {
2 private int numNuts = 0;
3
4 public void GrowNut() {
5 numNuts = numNuts + 1;
6 }
7
8 public bool PickNut(int numToPick) {
9 if (numToPick < 0) return false;
10 if (numToPick > numNuts) return false;
11 numNuts = numNuts - numToPick;
12 return true;
13 }
14
15 public int NumNuts {
16 get {
17 return numNuts;
18 }
19 set {
20 if (value < 0) return;
21 numNuts = value;
22 }
23 }
26 }
As you can see on line 2, the numNuts field is now private, meaning that only code within this class is allowed to access it. The GrowNut and PickNut methods remain unchanged; they can continue to update the numNuts field directly (the constraints in PickNut ensure that the value of numNuts remains legal). Since we still want code to be able to determine the number of nuts in a tree, we have added a public NumNuts property (note the capitalization, which distinguishes NumNuts the property from numNuts the field -- a pair of numNuts, so to speak):
15 public int NumNuts {
16 get {
17 return numNuts;
18 }
19 set {
20 if (value < 0) return;
21 numNuts = value;
22 }
23 }
The declaration of a property starts off just like a field, with an access modifier (public), the type (int), and the name (NumNuts), which is capitalized by convention. After those preliminaries, we define the accessors. The get accessor is used to retrieve the value of the property, while the set accessor is used to change it.
Accessors behave just like methods. The get accessor, which must always return a value of the type assigned to the property, in this example simply returns the value of the private numNuts field. Nothing too fancy here. The set accessor, however, which is always provided with a variable called value that contains the value that is to be assigned to the property, checks that this variable is greater or equal to zero (since we can't have a negative number of nuts) before storing it in the numNuts field.
Even in cases where any value is acceptable, you should make your objects' fields private and provide a property to access them. Doing this allows your programs to exhibit an important feature of object oriented programming called encapsulation.
Encapsulation means that the internal representation of an object is separated from the interface it presents to other objects in your program. In other words, a programmer that uses your class only needs to know what the public methods and properties do, not how they work. The advantage is that you can change how your class works to improve performance or add new features without breaking any code that relies on the methods provided by your original class.
For example, if you decided you wanted to represent each coconut as an individual object of class Coconut instead of using a single integer variable to keep count, you could make the necessary changes and still have the same property and two methods as the implementation above. Old code that was written with the original interface in mind would continue to work as before, while new code could take advantage of the new features (which would of course be provided by new methods).
As an exercise, rewrite the Tree class so that it correctly encapsulates its height field with a property.