developmentor - a developer services company				  
				      C# Tutorial
   Modules

Properties


Goals:

  • Show how to define and use properties.
  • Discuss static properties.
  • Briefly describe the advantages of using the C# property syntax.

Overview

Properties model the traits of an object or a class. C# provides special syntax to define and access properties. Programmers are encouraged to use the special syntax to implement properties because it results in clean client code and makes the intent of the class designer explicit to both human readers and automated tools.


Motivation

A class is typically a software model of a real world thing. The thing being modeled has certain properties; for example, a person has a name and an age, a stock has a symbol and a price, a circle has a radius, and so on. Other common terms for the same concept are trait, characteristic, or quality. A property can be implemented simply by defining a field to store the current value as shown below.

Client code often needs access to the property in order to read and/or write the value. The simplest way to achieve this is to make the fields public. Public data makes the resulting client code clean and simple. A write operation is accomplished by using the assignment operator to load a new value into the field and a read operation is a normal field access.

Despite its simplicity, public data is not used very often in practice since it has some disadvantages from a design point of view. One flaw is that there is no way for the class to perform error checking on the data being loaded into the fields. For example, a client could give a person a negative age or an empty name and the class would not be able to detect the error. Another problem is that there is no way to implement a read-only property since public data is implicitly readable and writeable by all external code. The common way to avoid the problems associated with public data is to make the data private and provide public read and write access methods. By convention, the access methods are typically named GetXXX and SetXXX where XXX is the name of the property in question. The private data / public access method pattern gives the class designer much more control than public data since the client no longer has direct access to the fields and must go through the access methods. This allows the access methods to perform error checking when new values are loaded. Any attempt to load invalid data can be rejected. A simple implementation without any error checking is shown below. It would be easy to extend this solution to include any needed if statements to perform any desired validation. It would also be trivial to make the property read-only simply by omitting the Set method.

The client code for properties implemented with access methods is not quite as clean as the public data case. The write operation for a public field uses an expression such as object.property = value; where the left hand side of the assignment operator is the property being modified and the right hand side is the new value. This syntax is intuitive since human readers generally find it easy to identify a line of code containing an assignment operator as a write operation. However, with an access method, the write operation is performed by calling the set method and passing the new value in as an argument. This syntax is arguably more difficult to visually identify as a write operation since the assignment operator is not used. A similar case can be made for a read operation. The read operation for a public field is typically a noun phrase such as object.property. This is intuitive since it agrees with the idea that a property should be a noun because it represents some trait of the type being modeled. In contrast, the read operation using a typical access method is a verb phrase such as object.GetXXX. This conflict can lead to client code that is less intuitive than when public data is used.


C# properties

The two goals of access control and clean client code are somewhat in conflict. Public data yields simple and intuitive client code but does not give the class designer enough control. Private data / public access methods provide the ability to do error checking and implement read-only properties but leads to less readable client code. To solve this dilemma, C# offers special syntax to implement properties that combines the advantages of both conventional techniques.

C# provides special language support for the implementation of properties which specifies a structured way to define the read and write accessors. There are five components of the property declaration: access level, type, name, write accessor, and read accessor. The basic structure is shown in the figure below.

Recall that a property definition typically has three components: an instance variable for data storage, a write access method, and a read access method. A C# property definition provides only the accessors and does not include any needed data storage. The most common case then, is to define a field to store the property data. The common wisdom suggests choosing a name for the field that is similar to the name of the property; for example, a variable called name for a property called Name (the difference in case is sufficient to make them distinct in C#).

The implementation of the accessors is perhaps the most interesting part of the syntax. The write accessor for a property is named set. The definition syntax is reminiscent of a traditional write access method but makes a few assumptions that reduce the amount of code required. Basically, the entire first line of a traditional write method is missing; that is, the return type, method name, and parameter list are not specified. This simplification makes sense because traditional write access methods all have the same form: a single argument whose type matches the type of the property and void return type. The main consequence of this minimal syntax is that the programmer does not have control over the name of the parameter; instead, the C# design team chose the name value for the implicit parameter. Other than the lack of the method header, the set accessor is much like a method. The body can contain an arbitrary set of statements to be run whenever the accessor is invoked.

The read access method for a property is named get. A traditional read access method takes no arguments and has a return type that matches the type of the property. Again, since this is so common, the property syntax does not contain these details explicitly. The body of the accessor specifies the statements to be run when the get accessor is used. The get accessor has an implied return type that matches the type of the property so the body is required to return an appropriate value or it is a compile time error. A complete property implementation is shown below.

The client code for C# properties is identical to accessing a public field. The compiler analyzes how the property is being used and invokes the appropriate accessor automatically. Specifically, the set accessor is invoked when the property is being used on the left hand side of the assignment operator while the get accessor is used in all other cases. Some sample client code is shown below.

The C# property syntax gives much of the power of the private data / public access methods pattern while retaining all the benefits of a public data implementation. In particular, a property can be read-only, write-only, or read-write. This is accomplished simply by providing or omitting the set or get accessors as desired. C# properties also give the class designer the ability to add any needed error checking code to the set and get implementations.


Static property

A property that applies to an entire class rather than to an instance can be created by applying the keyword static to the property definition as shown below. As with a static method, inside the accessors of a static property the instance methods and instance fields of the class are not accessible. That is, only the static parts of the class are usable and any attempt to access non-static members is a compile time error.

A static property must be accessed through the type name. It is a compile time error to attempt access using an instance of the class.


Benefits

The decision to support properties as a first class language feature is an interesting one. Adding the feature made the language larger and thus more difficult to learn; however, there are several good arguments as to why the special property syntax is worthwhile. First, the client code using the property syntax is much cleaner than using traditional access methods. Second, it makes the code more self documenting since otherwise, maintenance programmers would need to deduce the existence of a property from the presence of a pair of set/get methods. Finally, the property syntax allows property information to be carried through compilation and into the resulting IL code. The IL can be interrogated programmatically using the System.Reflection API and the properties of a class determined. Visual Studio 2010 makes heavy use of this feature to display Intellisense information and to populate properties windows for GUI components in the design tools.

This material is excerpted from the Programming C# course offered by DevelopMentor.