Static and Instance Members

The fields, properties, and methods of a class can be either instance members or static members . Instance members are associated with instances of a type, while static members are associated with the class and not with any particular instance. Methods are instance methods unless you explicitly mark them with the keyword static.

The vast majority of methods will be instance methods. The semantics of an instance method are that you are taking an action on a specific object. From time to time, however, it is convenient to be able to invoke a method without having an instance of the class, and for that, you will use a static method.

You access a static member through the name of the class in which it is declared. For example, suppose you have a class named Button and have instantiated objects of that class named btnUpdate and btnDelete.

Suppose that the Button class has an instance method Draw( ) and a static method GetButtonCount( ). The job of Draw( ) is to draw the current button, and the job of GetButtonCount( ) is to return the number of buttons currently visible on the form.

You access an instance method through an instance of the class—that is, through an object:

    btnUpdate.SomeMethod( );

You access a static method through the class name, not through an instance:

    Button.GetButtonCount( );

Invoking Static Methods

Static methods are said to operate on the class, rather than on an instance of the class. They do not have a this reference, as there is no instance to point to.

Static methods cannot directly access nonstatic members. You will remember that Main( ) is marked static. For Main( ) to call a nonstatic method of any class, including its own class, it must instantiate an object.

For the next example, use Visual Studio 2005 to create a new console application named StaticTester. VS.NET creates a namespace StaticTester and a class named Class1. Rename Class1 to Tester. Get rid of all the comments and the attribute [STATThread] that Visual Studio .NET puts above Main( ). Delete the args parameter to Main( ). When you are done, your source code should look like this:

    using System;
    namespace StaticTester
    {
         class Tester
         {
             static void Main( )
             {
             }
         }
    }

That is a good starting point. Until now, you’ve always done all the work of the program right in the Main( ) method, but now you’ll create an instance method, Run( ). The work of the program will now be done in the Run( ) method, rather than in the Main( ) method.

Within the class, but not within the Main( ) method, declare a new instance method named Run( ). When you declare a method, you write the accessor (public), followed by the return type, the identifier, and then parentheses:

    public void Run( )

The parentheses will hold parameters, but Run( ) won’t have any parameters, so you can just leave the parentheses empty. Create braces for the method, and within the braces, just print “Hello World” to the console:

    public void Run( )
    {
     Console.WriteLine("Hello world");
    }

Run( ) is an instance method. Main( ) is a static method and cannot invoke Run( ) directly. You will therefore create an instance of the Tester class and call Run( ) on that instance:

    Tester t = new 
 Tester( );

When you type the keyword new, IntelliSense tries to help you with the class name. You’ll find that Tester is in the list; it is a legitimate class like any other.

On the next line, invoke Run( ) on your Tester object t. When you type t followed by the dot operator, IntelliSense presents all the public methods of the Tester class, as shown in Figure 7-1.

IntelliSense

Figure 7-1. IntelliSense

Tip

Notice that the Tester class has a number of methods you did not create (Equals, Finalize, and others). Every class in C# is an object, and these methods are part of the Object class. This is covered in Chapter 11.

When your program is complete, it looks like Example 7-5.

Example 7-5. Instance methods

using System;
namespace StaticTester
{
   // create the class
   class Tester
   {
      // Run is an instance method
      public void Run( )
      {
         Console.WriteLine( "Hello world" );
      }

      // Main is static
      static void Main( )
      {
         // create an instance
         Tester t = new Tester( );

         // invoke the instance method
         t.Run( );
      }
   }
}

The output looks like this:

    Hello world

This is the model you’ll use from now on in most console applications. The Main( ) method will be limited to instantiating an object and then invoking the Run( ) method.

Using Static Fields

A common use of static member variables, or fields, is to keep track of the number of instances/objects that currently exist for your class. In the next example, you create a Cat class. The Cat class might be used in a pet-store simulation.

For this example, the Cat class has been stripped to its absolute essentials. The complete listing is shown in Example 7-6. An analysis follows the example.

Example 7-6. Static fields

using System;

namespace Test
{

   // declare a Cat class
   // stripped down
   public class Cat
   {
      // a private static member to keep
      // track of how many Cat objects have
      // been created
      private static int instances = 0;
      private int weight;
      private String name;

      // cat constructor
      // increments the count of Cats
      public Cat( String name, int weight )
      {
         instances++;
         this.name = name;
         this.weight = weight;
      }

      // Static method to retrieve
      // the current number of Cats
      public static void HowManyCats( )
      {
         Console.WriteLine( "{0} cats adopted", instances );
      }
      public void TellWeight( )
      {
         Console.WriteLine( "{0} is {1} pounds", name, weight );
      }
   }

   class Tester
   {

      public void Run( )
      {
         Cat.HowManyCats( );
         Cat frisky = new Cat( "Frisky", 5 );
         frisky.TellWeight( );
         Cat.HowManyCats( );
         Cat whiskers = new Cat( "Whisky", 7 );
         whiskers.TellWeight( );
         Cat.HowManyCats( );
      }

      static void Main( )
      {
         Tester t = new Tester( );
         t.Run( );
      }
   }
}

Here is the output:

    0 cats adopted
    Frisky is 5 pounds
    1 cats adopted
    Whisky is 7 pounds
    2 cats adopted

The Cat class begins by defining a static member variable, instances, that is initialized to zero. This static member field will keep track of the number of Cat objects created. Each time the constructor runs (creating a new object), the instances field is incremented.

The Cat class also defines two instance fields: name and weight. These track the name and weight of each individual Cat object.

The Cat class defines two methods: HowManyCats( ) and TellWeight( ). HowManyCats( ) is static. The number of Cats is not an attribute of any given Cat; it is an attribute of the entire class. TellWeight( ) is an instance method. The name and weight of each cat is per instance (each Cat has his own name and weight).

The Main( ) method accesses the static HowManyCats( ) method directly, through the class:

    Cat.HowManyCats( );

Main( ) then creates an instance of Cat and accesses the instance method, TellWeight( ), through the instance of Cat:

    Cat frisky = new Cat( )
    frisky.TellWeight( );

Each time a new Cat is created, HowManyCats( ) reports the increase.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset