Understanding static


There will be times when you will want to define a class member that will be used independently of any object of that class. Normally, a class member must be accessed through an object of its class, but it is possible to create a member that can be used by itself, without reference to a specific instance. To create such a member, precede its declaration with the keyword static. When a member is declared static, it can be accessed before any objects of its class are created and without reference to any object. You can declare both methods and variables to be static. The most common example of a static member is Main( ), which is declared static because it must be called by the operating system when your program begins.

Outside the class, to use a static member, you must specify the name of its class followed by the dot operator. No object needs to be created. In fact, a static member cannot be accessed through an object reference. It must be accessed through its class name. For example, if you want to assign the value 10 to a static variable called count that is part of a class called Timer, use this line:

 Timer.count = 10;

This format is similar to that used to access normal instance variables through an object, except that the class name is used. A static method can be called in the same way—by use of the dot operator on the name of the class.

Variables declared as static are, essentially, global variables. When objects of its class are declared, no copy of a static variable is made. Instead, all instances of the class share the same static variable. A static variable is initialized when its class is loaded. If no explicit initializer is specified, it is initialized to zero for numeric values, null in the case of object references, or false for variables of type bool. Thus, a static variable always has a value.

The difference between a static method and a normal method is that the static method can be called through its class name, without any object of that method being created. You have seen an example of this already: the Sqrt( ) method, which is a static method within C#’s System.Math class.

Here is an example that creates a static variable and a static method:

 // Use static. using System; class StaticDemo {   // a static variable   public static int val = 100;   // a static method   public static int valDiv2() {     return val/2;   } } class SDemo {   public static void Main() {     Console.WriteLine("Initial value of StaticDemo.val is "                       + StaticDemo.val);     StaticDemo.val = 8;     Console.WriteLine("StaticDemo.val is " + StaticDemo.val);     Console.WriteLine("StaticDemo.valDiv2(): " +                        StaticDemo.valDiv2());   } }

The output is shown here:

 Initial value of StaticDemo.val is 100 StaticDemo.val is 8 StaticDemo.valDiv2(): 4

As the output shows, a static variable is initialized when the program begins, before any object of its class is created.

There are several restrictions that apply to static methods:

  1. A static method does not have a this reference.

  2. A static method can directly call only other static methods. It cannot directly call an instance method of its class. The reason for this is that instance methods operate on specific instances of a class, but a static method does not.

  3. A static method must directly access only static data. It cannot directly use an instance variable because it is not operating on an instance of its class.

For example, in the following class, the static method valDivDenom( ) is illegal:

 class StaticError {   int denom = 3; // a normal instance variable   static int val = 1024; // a static variable   /* Error! Can't directly access a non-static variable      from within a static method. */   static int valDivDenom() {     return val/denom; // won't compile!   } }

Here, denom is a normal instance variable that cannot be accessed within a static method. However, the use of val is OK since it is a static variable.

The same problem occurs when trying to call a non-static method from within a static method of the same class. For example:

 using System; class AnotherStaticError {   // non-static method.   void nonStaticMeth() {      Console.WriteLine("Inside nonStaticMeth().");   }   /* Error! Can't directly call a non-static method      from within a static method. */   static void staticMeth() {     nonStaticMeth(); // won't compile   } }

In this case, the attempt to call a non-static (that is, instance) method from a static method causes a compile-time error.

It is important to understand that a static method can call instance methods and access instance variables of its class if it does so through an object of that class. It is just that it cannot use an instance variable or method without an object qualification. For example, this fragment is perfectly valid:

 class MyClass {   // non-static method.   void nonStaticMeth() {      Console.WriteLine("Inside nonStaticMeth().");   }   /* Can call a non-static method through an      object reference from within a static method. */   public static void staticMeth(MyClass ob) {     ob.nonStaticMeth(); // this is OK   } }

Here, nonStaticMeth( ) is called by staticMeth( ) through ob, which is an object of type MyClass.

Because static fields are independent of any specific object, they are useful when you need to maintain information that is applicable to an entire class. Here is an example of such a situation. It uses a static field to maintain a count of the number of objects that are in existence.

 // Use a static field to count instances. using System; class CountInst {   static int count = 0;   // increment count when object is created   public CountInst() {     count++;   }   // decrement count when object is destroyed   ~CountInst() {     count--;   }   public static int getcount() {     return count;   } } class CountDemo {   public static void Main() {     CountInst ob;     for(int i=0; i < 10; i++) {       ob = new CountInst();       Console.WriteLine("Current count: " +                         CountInst.getcount());     }   } }

The output is shown here:

 Current count: 1 Current count: 2 Current count: 3 Current count: 4 Current count: 5 Current count: 6 Current count: 7 Current count: 8 Current count: 9 Current count: 10

Each time that an object of type CountInst is created, the static field count is incremented. Each time an object is recycled, count is decremented. Thus, count always contains a count of the number of objects currently in existence. This is possible only through the use of a static field. There is no way for an instance variable to maintain the count because the count relates to the class as a whole, not to a specific instance.

Here is one more example that uses static. Earlier in this chapter you saw how a class factory could be used to create objects. In that example, the class factory was a non-static method, which meant that it could be called only through an object reference. This meant that a default object of the class needed to be created so that the factory method could be called. However, a better way to implement a class factory is as a static method, which allows the class factory to be called without creating an unnecessary object. Here is the class factory example rewritten to reflect this improvement:

 // Use a static class factory. using System; class MyClass {   int a, b;   // Create a class factory for MyClass.   static public MyClass factory(int i, int j) {     MyClass t = new MyClass();     t.a = i;     t.b = j;     return t; // return an object   }   public void show() {     Console.WriteLine("a and b: " + a + " " + b);   } } class MakeObjects {   public static void Main() {     int i, j;     // generate objects using the factory     for(i=0, j=10; i < 10; i++, j--) {       MyClass ob = MyClass.factory(i, j); // get an object       ob.show();     }     Console.WriteLine();   } }

In this version, factory( ) is invoked through its class name in this line of code:

 MyClass ob = MyClass.factory(i, j); // get an object

There is no need to create a MyClass object prior to using the factory.

Static Constructors

A constructor can also be specified as static. A static constructor is typically used to initialize attributes that apply to a class rather than an instance. Thus, it is used to initialize aspects of a class before any objects of the class are created. Here is a simple example:

 // Use a static constructor. using System; class Cons {   public static int alpha;   public int beta;   // static constructor   static Cons() {     alpha = 99;     Console.WriteLine("Inside static constructor.");   }   // instance constructor   public Cons() {     beta = 100;     Console.WriteLine("Inside instance constructor.");   } } class ConsDemo {   public static void Main() {     Cons ob = new Cons();     Console.WriteLine("Cons.alpha: " + Cons.alpha);     Console.WriteLine("ob.beta: " + ob.beta);   } }

Here is the output:

 Inside static constructor. Inside instance constructor. Cons.alpha: 99 ob.beta: 100

Notice that the static constructor is called automatically, and before the instance constructor. This can be generalized. In all cases, the static constructor will be executed before any instance constructor. Furthermore, static constructors cannot have access modifiers (thus, they use default access) and cannot be called by your program.




C# 2.0(c) The Complete Reference
C# 2.0: The Complete Reference (Complete Reference Series)
ISBN: 0072262095
EAN: 2147483647
Year: 2006
Pages: 300

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