Learning C# and OOP, Properties, Part 1Richard Baldwin explains properties in C# and provides a comparison between C# properties and Java properties. He also explains the importance of properties with respect to reflection and introspection. Published: October 29, 2002
C# Programming Notes # 106a
PrefaceThis lesson is part of a miniseries designed to teach you how to write object-oriented programs using C#. This miniseries will describe and discuss the necessary and significant aspects of object-oriented programming (OOP) using C#. The first lesson in the miniseries was entitled Learning C# and OOP: Getting Started, Objects and Encapsulation. The previous lesson was entitled Learning C# and OOP, Classes. Comparisons with Java The miniseries will also make comparisons between C# and Java with respect to both syntax and OOP concepts. I will emphasize the similarities between these two programming languages, which are likely to dominate the programming world in the foreseeable future. By studying these lessons and learning about OOP using C#, you will also be learning quite a lot about OOP using Java. Relatively high level I will provide the information in a high-level format, devoid of any prerequisite requirement to know C# syntax. In those cases where an understanding of C# syntax is required, I will provide the necessary syntax information in the form of sidebars and sample programs. Therefore, if you have a general understanding of computer programming, you should be able to read and understand the lessons in this miniseries, even if you don't have a background in object-oriented programming, or a background in the C# programming language. Viewing tip You may find it useful to open another copy of this lesson in a separate browser window. That will make it easier for you to scroll back and forth among the different listings while you are reading about them. Supplementary material I recommend that you also study the other lessons in my extensive collection of online programming tutorials. You will find a consolidated index of my online tutorial lessons at www.DickBaldwin.com. PreviewFirst of two parts This is the first part of a two-part lesson that will concentrate on properties in C# and a comparison of C# properties with Java properties. A sample C# program is provided to illustrate C# properties. A sample Java program is also provided to illustrate the similarity of properties between C# and Java. Methods and fields You will see that C# properties act like methods to the creator of the class but look like public fields to clients of the class. As a result, public fields and properties are indistinguishable to readers of the C# code who don't have ready access to documentation on the class. You will also see that Java properties look like methods to clients of the class, and it is impossible to confuse properties with public fields in Java. Properties are used for essentially the same purpose in both languages. Properties support data hiding Both C# properties and Java properties provide the data hiding generally required by good object-oriented design. However, properties are not a prerequisite for data hiding. Data hiding can be easily accomplished in either C# or Java in the absence of properties. Reflection and introspection Perhaps the most important characteristic of properties has to do with reflection and introspection. This is a process whereby one object can discover and manipulate the properties belonging to another object, instantiated from a class that may not have existed when the class of the first object was defined. Reflection and introspection will be discussed in detail in the second part of this two-part lesson. Bound properties and constrained properties Another important characteristic of properties has to do with bound properties and constrained properties. This is a process by which an object can be automatically notified when the value of a bound or constrained property belonging to another object changes. A brief discussion of bound and constrained properties will be provided in the second part of this lesson. C# and Java properties are very similar Properties are so similar between C# and Java that if you understand
properties in either language, you should have no difficulty understanding
properties in both languages.
Discussion and Sample CodeWhat is a property? In C#, a property is created by including a special block of code in a class definition. The syntax of this special block of code is unlike anything else in C#. In Java, a property is created by including one or both of a pair of set and get methods meeting a certain format specification in a class definition. By the time you finish studying the two parts of this lesson, you should know what properties are, and you should know how to create and use them in both C# and Java. What others have to say about properties Let's begin with what others have to say about properties. Here is what Microsoft has to say in the documentation for the PropertyInfo class:
Programming C# by Jesse Liberty Here's what Jesse Liberty has to say about properties in his O'Reilly book entitled Programming C#.
As you will see later, this description is true for C# properties, but is not true for properties in general. C# In A Nutshell Here is what the authors of C# In A Nutshell from O'Reilly have to say on the matter:
This is true, of course, but there seems to be something missing. The same data-hiding benefits can be, and have been, achieved by C++ programmers for years, using simple accessor methods. Data hiding is made possible by the availability of access modifiers for class members. Typically data hiding is achieved by providing public methods for accessing private instance variables. While properties generally use this same scheme, properties are not a prerequisite for data hiding. C# Primer, A Practical Approach Here is what Stanley Lippman has to say in C# Primer, A Practical Approach from Addison-Wesley.
What does Dick Baldwin have to say on the matter? In my opinion, all of the above descriptions have missed the mark in terms of what properties are really all about. If the benefits of properties were limited to the above descriptions, it would not have been worth the effort for Microsoft to develop a new and cryptic syntax for properties. Similarly, it would not have been worth the effort for Sun to develop design patterns for properties. The real importance of properties is not based on making methods look like fields. Also, the importance is not based on data hiding. Rather, the real importance of properties has to do with reflection and introspection, which I will discuss in detail in the second part of this two-part lesson.
Fields or methods? Liberty's statement that "properties, ... act like methods to the creator of the class but look like fields to clients of the class" is true for C#, but is not true in general. In my opinion, whether properties look like fields or look like methods is immaterial to the experienced programmer. I can't imagine that an experienced OOP programmer would care one way or the other. Java has provided the benefits of properties in its JavaBeans Component technology for several years, and Java properties do not look like fields to clients of the class. Rather, they look like simple method invocations to clients of the class. In the six or more years that I have been involved in Java, I have yet to hear anyone complain that Java properties don't look like fields. Not a prerequisite for data hiding As mentioned earlier, the availability of properties is not a prerequisite for the "data hiding required by good object-oriented design." Data hiding has been easily accomplished for many years in C++ using private instance variables and public accessor methods with no concept of properties being involved. My description of a property The following paragraphs contain my description of a property. This description is based on practical considerations. For the most part, I will describe the things that must be true for a property to exist, and more importantly, to be really useful. Name, type, and value First, a property must have a name, a type, and a value, and possibly some other attributes as well, (such as being read only or read/write).
Same name and type, but different value A property belongs to an object. Every object instantiated from the same class will have the same set of properties. The properties belonging to all the objects instantiated from the same class will have the same names and types, but won't necessarily have the same values from one object to the next. Where is the value stored? The value of a property is probably most commonly stored in an instance variable belonging to the object, but that is not a requirement. The value could be stored in a database, or a disk file, or elsewhere, or could be computed on-the-fly when requested. The state of the object The value of a property generally contributes to the state of the object to which it belongs, and when the value of the property changes, the state of the object changes accordingly.
Standardization is required To be really useful, the access methodology for a property must be predefined and standardized within a given programming language. However, the access methodology need not be the same from one language to the next. As mentioned earlier, C# accesses properties as fields, while Java accesses properties as methods. The real importance of properties It must be possible for executing code to learn everything there is to know about the properties belonging to a (previously unknown) object at runtime, and to be able to access those properties for reading and writing at runtime. This must be possible even though the author of the executing code had no knowledge of the unknown object's class when the code was originally written.
Because .NET is language-neutral, this capability must exist across all languages supported by .NET, even if the language used to define the class and its properties is different from the language used to instantiate objects from the class. A real-world example Let me describe a real-world example of what I mean. Ever since the introduction of Visual Basic several years ago, software developers have been interested in using standard software components to develop software. Using software components to develop software is similar to using electronic components to manufacture electronic devices. The great promise of using standard software components to develop software is that it can reduce the cost of software development in the same way that the use of standard electronic components has reduced the manufacturing cost of electronic devices such as computers. A toolkit full of software components In this style of programming, the programmer has access to a toolkit full of software components, and a builder tool that can be used to wire those software components together in order to produce a software application. A sophisticated computer program The builder tool itself is a very sophisticated and complex computer program. In order for the builder tool to wire software components together, according to the wishes of the programmer, the builder tool must be able to extract the following information (as a minimum) from each software component that is installed in the toolkit:
Components need to communicate For example, when two components are wired together, one component may need to access, and possibly modify, property values belonging to the other component. This is only possible if the builder tool can discover everything that it needs to know about the properties of every component in the toolkit. (The builder tool is unable to read the documentation for a software component the way you and I do.) Property editors Even before getting to the point where one component needs to access the properties belonging to another component, the builder tool itself usually needs to discover and access the properties of every component being used to develop an application. Most builder tools provide a property editor as a graphical user interface (GUI). The property editor makes it possible for the programmer to set initial property values on every software component so that the program being developed will start running with all of its component objects in the correct state. For example, the programmer will normally want to set the location, height, width, text, and color of each visual button so that it will be in the correct location with the correct size, text, and color when the program starts running. As distinguished from data hiding In my opinion, the ability to accomplish this under software control is what separates properties from ordinary data hiding that we have been practicing for many years. Should properties look like fields or methods? The ability to accomplish the discovery of properties at runtime has nothing to do with whether the property looks like a field or looks like a method. It has been done successfully both ways. Some programmers may prefer one approach to the other, but in reality, the difference is trivial. To an experienced programmer, the difference in programming effort between the two approaches is negligible. Self-documenting code In my opinion, however, the approach where the property looks like a method is the more self-documenting of the two. This approach produces code that is easier to read and understand by interested third parties who don't have ready access to the class documentation. We have been striving for years to develop better self-documenting programming styles. Making properties look like fields instead of methods is a step backwards in my opinion. However, from a technical viewpoint, it can obviously be done either way. What really matters is ... What really matters is that the mechanism for accessing properties be predefined and standardized so that code can discover and manipulate the properties at runtime. Common at the MSIL level It is also a requirement that regardless of the programming syntax used by the different languages supported by .NET, they must all compile to the same result at the Microsoft Intermediate Language (MSIL) level.
C# and Java approach standardization in different ways, and they both seem to work very well. Even though the standardization approach is different between the two languages, the underlying concepts being implemented are very similar. The C# approach to standardization The C# approach uses a special source-code syntax to create a property. You will see an example of this syntax in the sample program to be discussed later. As far as I know, this special syntax must be used in all cases where you need to create a property in C#. The Java approach to standardization Java allows for two different approaches. The simplest Java approach makes use of JavaBeans Design Patterns, which are nothing more than a set of well-defined naming conventions. Using this approach, you can create a property in Java by causing the signatures of a pair of set and get methods to adhere to the design pattern specifications. You will also see an example of this approach in the programs to be discussed later. The other approach allowed by Java involves considerably more work. With this approach, you must define a companion or helper class that implements a rather complex interface named BeanInfo. An object instantiated from this helper class can be queried to discover the properties belonging to objects of the class that it is designed to help. You won't see an example of this approach in this lesson. If you would like to learn more about this approach, see my tutorial lesson entitled JavaServer Pages and JavaBean Components, Part III. (In addition to providing additional information about this approach, this lesson also provides an interesting example of the use of the discovery process.) It's time to look at some code I'm going to show you a C# program that illustrates properties from three different viewpoints:
The third viewpoint contains some powerful material, and the discussion of the third viewpoint will be deferred until the second part of this two-part lesson. While you might find it complex, I hope that you will stick with it until you understand the concepts involved. A comparable Java program In addition, I'm going to show you a comparable Java program that accomplishes exactly the same thing. I will compare the code between the two programs and discuss the similarities and the differences. You will see that even at the complex level of the third viewpoint, the concepts, and even the syntax in the C# program is very similar to the Java program. Explain in fragments The complete C# program is shown in Listing C11, and the complete Java program is shown in Listing J8. These two listings are near the end of the lesson. In order to help you to focus specifically on important sections of code, I will explain the behavior of these programs in fragments. A target class The C# program consists of two classes. The first class that I will discuss is named TargetClass. This class defines some properties (as well as some other members), which are accessed by code in the Main method of the other class named Props01. Listing C1 shows the beginning of the code for the definition of the
class named TargetClass. Here we are seeing things from the
viewpoint of the developer of the class named TargetClass.
A public instance variable The class named TargetClass declares a public instance variable of type string named text. There's nothing exciting about a public instance variable. I included it for demonstration purposes only. I will show that there is no discernible difference between accessing a public instance variable and accessing a property in C#. Implementing data hiding the conventional way Listing C2 shows a pair of set and get methods that accomplish data hiding for this C# program.
Not a property in C# However, this is not a Java program. It's a C# program. The signatures of these two methods do not create a property in C#. A different syntax is required to create a property in C#. This will be confirmed in the second part of this two-part lesson when we write program code to discover the properties of an object of this class. A C# property C# uses the syntax shown in boldface in Listing C3 to create a property named height.
There isn't much more for me to tell you about this syntax. You will simply need to memorize it (pay particular attention to the number and location of the curly braces). The property value In this case, the property value is stored in the instance variable named heightData. However, that is not a requirement. The code could be written to store the property value in a database, in a disk file, or in any other location accessible by the code in the object. The name and type of the property The name and type of the property is established by the line of code that reads public int height{ In this case, the property is named height and it is type int. The get method Although they don't look like methods, this code effectively contains two methods named get and set. Whenever the using code references the property name in a fetching sense, the code in the get block is executed. This block must contain a return statement to return a value of the specified type. The get block could also contain any other code that you might want to have executed in conjunction with such a fetch operation. An example of a fetch operation is highlighted in boldface below, where obj is a reference to an object instantiated from this class. Console.WriteLine("height: " + obj.height); The set method and the value parameter Whenever the using code references the property name in a storage sense (as the left operand of an assignment operator, for example), the code in the set block is executed. The value to be stored (the right operand of the assignment operator, for example) is passed to the set code as a hidden parameter named value. The name of this hidden parameter never changes. The code in the set block must save the value of the hidden parameter named value in an appropriate location if it is to be successfully returned later. Additional code You can place any code that you might want to have executed in conjunction with such a set operation in the set block. Data validation code is particularly appropriate here. An example of such a storage operation is shown below where obj is a reference to an object instantiated from this class. obj.height = 20; In this case, the hidden parameter named value will have an int value of 20. Another property named width Listing C4 shows code that defines another property of type int
named width. This code uses the same syntax as that used for
the property named height.
This is the end of the class definition for the class named TargetClass. An object of type TargetClass An object instantiated from the class named TargetClass contains:
Switching viewpoints Now its time to switch to the viewpoint of the user of the class named TargetClass. This user already knows the names and types of the properties and has no interest in discovering properties at runtime. The Main method Listing C5 shows the beginning of the class named Props01 and the beginning of the Main method in that class. This code begins by instantiating and saving a reference to a new object of the class named TargetClass discussed above. The reference is saved in the reference variable named obj. The reference to this object will be used to access the public instance variable, the hidden data, and the properties of this object.
Access the public instance variable The code in Listing C6 uses the object's reference to directly store
the string "Quit" in the public instance variable named text.
Following this, the code uses the object's reference to directly get and
display the value in the public instance variable named text.
Will compare with property access methodology There is nothing particularly interesting about the code in Listing C6. This code is presented here for later comparison with code that accesses the properties. The code in Listing C6 produces the following output on the screen. text: Quit Accessing the hidden data The code in Listing C7 uses the two accessor methods to first set a
value in the private instance variable, and then to get and display that
value. Note that data hiding is fully supported here without the
use of properties.
Listing C7 is a straightforward application of simple data hiding using accessor methods. No special support of any kind is required to use this technique. The code in Listing C7 produces the following output on the screen: color: 15 Accessing a property Now we are going to access a C# property in a simple non-discovery way.
This is shown in Listing C8.
The code in Listing C8 sets the value 20 in the property named height. Appears to access a public field Note that the syntax of this statement looks exactly like the syntax of the first statement in Listing C6 (except that the data type is different), which assigns a value directly to a public instance variable. Without having access to the documentation for the class named TargetClass, it would not be possible for the reader of this code to know whether height is the name of a property or is the name of a public instance variable. Not self-documenting code This is what I meant earlier when I said that this approach to property access is not self-documenting. For the experienced programmer, the first statement in Listing C7, which invokes a method, is no more challenging than the statement in Listing C8, which appears to access a public field. I can't imagine why an experienced programmer would prefer for properties to look like public fields, given the significant loss in self-documentation that results from that design. Other than the self-documentation aspect, however, it seems to me that this difference is a trivial syntax issue. Display the property value. Listing C9 gets and displays the value stored in the property named
height.
Again, this looks like the code is accessing a public field named height. Without having access to the documentation for the class named TargetClass, the reader of the code would have no way of knowing any different. The code in Listing C9 produces the following output on the computer screen: height: 20 Accessing another property Listing C10 first sets, and then gets and displays the value of the
property named width.
There's nothing new here. The code in Listing C10 produces the following output on the computer screen: width: 50 A comparable Java program Now I'm going to show you a Java program that accomplishes exactly the same thing as the C# program discussed above. As with the C# program, the Java program will illustrate properties from three significantly different viewpoints:
As was the case with the C# program, the third viewpoint contains some powerful material, and will be discussed in detail in the second part of this two-part lesson. While you might find it somewhat complex, I hope that you will stick with it until you understand the concepts involved. The most significant aspect of the third viewpoint will be the remarkable similarity between the C# code and the Java code, even at this complex level. Explain in fragments The complete Java program is shown in Listing J8 near the end of the lesson. As usual, in order to help you to focus on important sections of code, I will explain the behavior of this program in fragments. A target class As was the case with the C# program, the Java program consists of two classes. The first class that I will discuss is named TargetClass. This class defines some properties, which are accessed by code in the main method of the other class named Props01. Listing J1 shows the beginning of the definition of a Java class that
mimics the behavior of the C# class shown in Listings C1 through C4.
Here we are seeing things from the viewpoint of the developer of the class
named TargetClass.
Serializable interface This Java class implements the Serializable interface. Without getting into the details, let me just say that this is required to cause the class to satisfy the JavaBeans Component specification, making it suitable for introspection. (Introspection will be explained and illustrated in the second part of this two-part lesson.) Class not declared public Note that unlike the C# class in Listing C1, I didn't declare the Java class public. Rather, by not declaring an access level, I caused this class to be package private by default. This was done strictly for convenience. In Java, every public class must be defined in a separate source code file. I made this class package private to avoid the requirement to create and maintain separate source code files for each of the class definitions in the program. (Java access of package private is similar to internal access in C#.) A public instance variable As was the case with the C# class in Listing C1, this class definition begins with the declaration of a public instance variable. This instance variable will be used later to illustrate that access to a property in Java has no resemblance to access to a public instance variable. Therefore, it isn't possible to confuse the two. A property named color The Java code in Listing J2 is identical to the C# code in Listing C2.
As is the case in C#, the code in Listing J2 accomplishes data hiding by providing public accessor methods for a private instance variable. Perhaps more important, the code in Listing J2 creates a Java property named color. This is all that is required to create a property in Java. No special and unusual source code syntax is required. All that is required is to provide accessor methods that satisfy the JavaBeans Design Pattern for property accessor methods, and these two methods meet that requirement. The name and type of the property According to the JavaBeans Design Pattern for property accessor methods, the name of the Java property is the word following get or set in the name of the accessor methods, with the case of the first character flipped. The type of the property is the same as the type of the single argument of the set method, which must match the return type of the get method. The property value For the code in Listing J2, the property value is stored in the instance variable named colorData. However, as with C#, this is not a requirement. The code could be written to store the property value in a database, in a disk file, or in any other location accessible by the code in the object. Properties named height and width The code in Listing J3 creates two more Java properties named height
and width.
The code in Listing J3 is different from the C# code in Listings C3 and C4 used to create C# properties named height and width. This is because Listings C3 and C4 used the special syntax required to create properties in C#. In the end, however, the properties behave essentially the same way in both languages. Listing J3 is also the end of the Java class definition for the class named TargetClass. An object of type TargetClass A Java object instantiated from the class named TargetClass contains:
Switching viewpoints Now its time to switch to the viewpoint of the user of the class named TargetClass. This user knows the names and types of the properties and has no interest in discovering properties at runtime. The main method Listing J4 shows the beginning of the class named Props01 and
the beginning of the main method for that class. Except for
the difference in the signature of the main method, (which I
explained in an earlier lesson), the Java code in Listing J4 is identical
to the C# code in Listing C5.
The code in Listing J4 begins by instantiating and saving a reference to a new object of the class named TargetClass discussed above. The reference is saved in the reference variable named obj. The reference to this object will be used to access the public instance variable and the properties of this object.
Access the public instance variable As was the case in the C# program, the code in Listing J5 uses the object's reference to directly store the string "Quit" in the public instance variable named text. Following this, the code uses the object's reference to directly get and display the value in the public instance variable named text.
Will compare with property access methodology There is nothing particularly interesting about the code in Listing J5. This code is presented here for later comparison with code that accesses the properties. The code in Listing J5 produces the following output on the screen. text: Quit Accessing the property named color The code in Listing J6 uses the two property access methods to first
set a value in the property named color, and then to get and display
that value. Note that data hiding is fully supported here.
Again, except for the different syntax used for console output, the Java code in Listing J6 is identical to the C# code in Listing C7. The difference, however, is that this Java code involves setting and getting a property value, while that is not the case with the C# code. The code in Listing J6 produces the following output on the screen: color: 15 Syntax comparison It is also important to note that this property access syntax bears no resemblance to the code in Listing J5, which accesses a public instance variable. There is no chance of confusing public instance variables with properties in Java. Thus, the syntax used for accessing properties in Java is more self-documenting than the syntax used for accessing properties in C#. Accessing the properties named height and width The code in Listing J7 uses the property access methods to first set,
and then get and display the values in the properties named height
and width.
Compare the bottom half of the code in Listing J7 (width property access) with the C# code in Listing C10 to see a direct comparison of the difference in property access mechanisms in C# and Java. There's nothing new here, so I won't discuss it further. The code in Listing J7 produces the following output on the computer screen: height: 20
SummaryConcentrate on properties This lesson has concentrated on properties in C# and a comparison of C# properties with Java properties. A sample C# program was provided to illustrate C# properties. A sample Java program was also provided to illustrate the similarity of properties in C# and Java. Methods and fields C# properties act like methods to the creator of the class but look like public fields to clients of the class. As a result, public fields and properties are indistinguishable to readers of the code who don't have ready access to documentation on the class. Java properties look like methods to clients of the class. As a result, it is impossible to confuse properties with public fields in Java. In my opinion, Java properties are more self-documenting than C# properties. Beyond this, however, properties are used for essentially the same purposes in both languages. Properties support data hiding Both C# properties and Java properties provide the data hiding generally required by good object-oriented design. However, properties are not a prerequisite for data hiding. Data hiding can be easily accomplished in C#, Java, or C++ in the absence of properties. C# and Java properties are very similar Properties are so similar in C# and Java that if you understand properties in either language, you should have no difficulty understanding properties in both languages. What's Next?Reflection and introspection Perhaps the most important aspect of properties has to do with reflection and introspection. This is a process whereby one object can discover and manipulate the properties belonging to another unknown object even though the author of the executing program had no knowledge of the unknown object's class when the executing program was originally written. This will be discussed in detail in the second part of this two-part lesson. Bound properties and constrained properties Another important characteristic of properties has to do with bound properties and constrained properties. This is a process by which an object can be registered to be automatically notified when the value of a bound or constrained property belonging to another object changes. Indexed properties In a future lesson, I will teach you about indexed properties. These are properties containing multiple values, with each value being accessible through a numeric index. Complete Program ListingsA complete listing of the C# program discussed in this lesson is shown
in Listing C11.
A complete listing of the Java program discussed in this lesson is shown
in Listing J8.
Review QuestionsThe second part of this two-part lesson will contain review questions, answers, and explanations for both parts of the lesson.
Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas. He is the author of Baldwin's Programming Tutorials, which has gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine. Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.
-end- |
© 1996, 1997, 1998, 1999, 2000, 2001, 2002 Richard G. Baldwin |