Properties


Properties represent state in a class. However, properties are quite different from fields. Whereas a field stores data, a property provides a specific access point to that data. Properties extend the concept of the field by being able to restrict the incoming values and provide read-only and write-only data members.

Java and C++ Note:

Java and C++ do not have a concept of a property. However, Java has a well-defined pattern for exposing fields in an equivalent manner. A standard practice in Java is to create getFieldName() and setFieldName() methods to perform a similar task to properties. Think of properties in .NET as a formalized implementation of this pattern.

To build on the last example, if the business requirement stated the value of the balance could not be below zero, then the rules would be applied when the property is set. In our next example, if the argument violates the rule, then we will throw an ArgumentOutOfRangeException. The following program (properties_bankaccount.cs) illustrates this:

    using System;    public class Account    {      private double balance;      public double Balance      {        get        {          return balance;        }        set        {          if (value < 0)              throw              new ArgumentOutOfRangeException("value","Balance must                                               be greater than 0");          balance=value;        }      }    } 

If you'll notice, we refer to value but have not declared it anywhere. The value keyword is implicitly set when the property is set. For example, myAccount.Balance=500 would load 500 into the value parameter that we reference in the set method:

    class AtTheBank    {      [STAThread]      static void Main(string[] args)      {        Account myAccount = new Account();        try        {          Console.WriteLine("You have " + myAccount.Balance + "                             remaining.");          myAccount.Balance=10000;          Console.WriteLine("You have " + myAccount.Balance + "                             remaining.");          myAccount.Balance=-500;          Console.WriteLine("You have " + myAccount.Balance + "                             remaining.");        }        catch(ArgumentOutOfRangeException e)        {          Console.WriteLine("Bad value!");        }      }    } 

Properties have greater flexibility in how to expose data to external classes. Properties provide data encapsulation. In our example, the user does not have direct access to the account balance any more. Rather, the account balance can only be accessed through the Balance property. The Balance property, in turn, enforces a basic business rule on setting the actual account balance. To the rest of the world, the balance is as easy to access as a public field, but now only the Account class is responsible for enforcing business rules.

The advantage of using data encapsulation comes when the implementation of the class needs to change. Data encapsulation allows us to control what values the user can assign to a property, giving us the power to prevent an invalid state since we can filter and possibly reject incoming values if they would incorrectly disrupt the object's state. In our example, if the rule later changes to allow negative balances, but only to $500, then we could change the Account class and not disrupt any other class that relies on Account. Properties also provide additional value over simply public fields in that a property can be defined as read-only or write-only.

In C#, defining a property as read-only or write-only is as simple as removing the appropriate setter or getter respectively. The compiler will throw an error at build time if we attempt to get the value of a write-only property or try to set a read-only value. This includes attempting to access a write-only property on the right-hand side of an expression or within a statement.

Within the .NET environment, properties are somewhat different from other type members. Within MSIL, properties are broken down into get_ and set_ methods. For example, our read-write property Balance would have both a get_Balance and set_Balance accessor method defined within the Account class's MSIL. The compiler will also emit a property definition into the MSIL to provide the association between the property and the get_ and set_ access methods. Let's go back to our Account Balance property:

    using System;    public class Account    {      private double balance;      public double Balance      {        get        {          return balance;        }        set        {          balance=value;        }      }    } 

However, the question may be, why even have properties at all. If the entire purpose of a property is to redirect to other accessors, then why not just add two methods to act as accessors to the private field and bypass the use of properties altogether.

Well, the easiest answer is that properties help immensely with readability. Consider the following two equivalent methods of setting the account balance:

    Account myAccount = new Account();    double myBalance;    myAccount.Balance=1000;    myBalance=myAccount.Balance; 

versus:

    myAccount.setBalance(1000);    myBalance=myAccount.getBalance(); 

While both function well, the first is much easier to follow and seems a bit more natural to most people. Additionally, development tools like Visual Studio .NET use the property MSIL block to provide more detailed information about the class to the developer. For example, when Visual Studio .NET provides automatic code completion, it can distinguish between a method and a property and gives the property a different icon for display purposes.

However, the first approach of using properties does come with one downside. As you will recall, we discussed how fields could be assigned different accessibility levels. This holds true for properties as well. The downside is that an accessibility level can only be applied to the property; it cannot be applied to the get and set accessors separately. If, for any reason, the accessors must have different visibilities, such as a public get and a protected set, then a property will no longer be the right solution. In instances where you need separate accessibility levels, you will need to define your own getter and setter methods. Properties are covered in more detail in Chapter 4.




C# Class Design Handbook(c) Coding Effective Classes
C# Class Design Handbook: Coding Effective Classes
ISBN: 1590592573
EAN: 2147483647
Year: N/A
Pages: 90

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net