Fields


Fields, more commonly referred to as instance variables or class variables, are the most basic building blocks in most classes and structs. Quite simply, fields store data and references for classes and structures. A field is simply a variable defined in a class.

If not exposed and used correctly, fields can lend themselves to elusive bugs. You will see where some of the bugs can be introduced when we talk about accessibility. Fields can have five different levels of accessibility:

  • public
    The access is not limited. A consumer of your class can freely read and modify any public fields, without your class even being aware of the changes. Public fields should be used with caution.

  • internal
    Access to internal fields is restricted to the same namespace as your class. In essence, this is stating, "Only other types in my namespace can read or modify this field directly." As with public fields, your class will still not be aware of the changes. Internal fields should also be used with caution.

  • protected
    Access is limited to classes that are inherited or extended from your class, and your own class of course. Remember, an important part of OO design is the ability to inherit from other classes. This states, "Only myself and types that are derived from me can access this field."

  • protected internal
    This is the only valid two-keyword access modifier. This combines the meaning of both protected and internal to mean "Myself, other types in my namespace, or types derived from me, can access this field."

  • private
    This is the most restrictive of the access declarations. A private field means, "Only I can access this field. No other types in my namespace, nor any types derived from me can even see this field."

At this point, it is important to understand that proper exposure is essential in class design. For example, if a field is public, then it is possible for consumers of your class to modify the contents of a field without your class ever knowing about the changes.

A field is simply a variable defined in a class. When the .NET runtime creates an instance of the class, memory is allocated to hold the contents of the instance fields. Because the field is created at run time and has its own memory space, the field is not subject to the versioning problems associated with constants. This contrasts with a constant where the value is substituted in at compile-time. If a constant changes, the dependent classes must also be recompiled. If a field changes, the dependent classes are not affected as they simply hold a reference to the field.

Let's take a minute to demonstrate what a field looks like. As an added bonus, this will demonstrate why it is essential to pay attention to access modifiers on class fields. The following program (fields_publicbankaccount.cs) creates an object of type Account. The class Account is a very basic representation of a bank account with just one field (right now) to store the account's balance. Since the balance field is a double, the compiler will initialize it to a value of 0. Default values and class initialization are covered in greater detail in Chapter 5.

    using System;    public class Account    {      public double balance;    }    class AtTheBank    {      [STAThread]      static void Main(string[] args)      {        Account myAccount = new Account();        Console.WriteLine("You have " + myAccount.balance + "                           remaining.");        myAccount.balance=10000;        Console.WriteLine("You have " + myAccount.balance + "                           remaining.");      }    } 

Compiling and running the above produces the following output:

    C:\Class Design\Ch 02>fields_publicbankaccount.exe    You have 0 remaining.    You have 10000 remaining. 

Looking at the MSIL created for the Account class, we notice the balance field is given its own location. The MSIL simply confirms that the balance variable is of type float64 (double) with public access and that it is called balance:

click to expand

By making this field public, we have made it part of the class's interface. This means that if we need to change the field name later, we will break binary compatibility. Additionally, and as you saw above, by making the field public, we have given unrestricted access to any other class that instantiates our class. In certain cases, this is acceptable and even desired. However, in most cases, and certainly in our bank account example, we do not want to allow others to change our field state. After all, it might not be desirable to let bank customers determine their own balances!

Public fields are simple to use, but are very dangerous and not recommended for two reasons:

  • Public fields are unrestricted
    In this example, the AtTheBank class can change the value of the balance to any float64 value. If the requirement is that the balance can never be less than 0, then every piece of code that uses the Account class must enforce this rule before setting the public balance field. In other words, we allow clients to modify the field even if they don't understand all of the attendant business rules.

  • Public fields make the class difficult to version
    Once deployed, we cannot change the name of the balance field, as the binary compatibility will be compromised. We also cannot turn the public fields into a property without compromising binary compatibility.

In practice, public fields should be avoided unless special justification can permit their use. For instance, sometimes it may be desirable to have a class or struct that simply stores state to be passed between other classes. However, as a rule, any data that is to be exposed on a public interface is more flexible in the form of a property.




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