4.3 Using Static Members

The properties and methods of a class can be either
instancemembers or
staticmembers. Instance members are associated with
instances of a type, while static members are considered to be part
of the class. 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 as well that the
Button class has a static method
SomeMethod( ). To access the static method, you
write:

Button.SomeMethod( );

rather than writing:

btnUpdate.SomeMethod( );

In C#, it is not legal to access a static method or member variable
through an instance, and trying to do so will generate a compiler
error (C++ programmers, take note).

Some languages distinguish between class methods and other (global)
methods that are available outside the context of any class. In C#
there are no
global methods, only class methods, but
you can achieve an analogous result by defining static methods within
your class.

VB6programmerstakenote: Don't confuse the
static keyword in C# with the
Static keyword in VB6 and VB.NET. In Visual Basic,
the Static keyword declares a variable that is
only available to the method it was declared in. In other words, the
Static variable is not shared among different
objects of its class (i.e., each Static variable
instance has its own value). However, this variable exists for the
life of the program, which allows its value to persist from one
method call to another.

In C#, the static keyword indicates a class
variable. In VB, the equivalent keyword is Shared.

Static methods act more or less like global methods, in that you can
invoke them without actually having an instance of the object at
hand. The advantage of static methods over global, however, is that
the name is scoped to the class in which it occurs, and thus you do
not clutter up the global namespace with myriad function names. This
can help manage highly complex programs, and the name of the class
acts very much like a namespace for the static methods within it.

Resist the temptation to create a single class in your program in
which you stash all your miscellaneous methods. It is possible but
not desirable and undermines the encapsulation of an object-oriented
design.

4.3.1 Invoking Static Methods

The Main( ) method
is static. 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.

Javaprogrammerstakenote: In C#, calling
static methods through instance variables is not permitted.

SomeMethod( ) is a nonstatic method of
MyClass. For Main( ) to access
this method, it must first instantiate an object of type
MyClass and then invoke the method through that
object.

4.3.2 Using Static Constructors

If your class declares a
static
constructor, you will be guaranteed that the static constructor will
run before any instance of your class is created.

You are not able to control exactly when a static constructor will
run, but you do know that it will be after the start of your program
and before the first instance is created. Because of this, you cannot
assume (or determine) whether an instance is being created.

For example, you might add the following static constructor to the
Time class from Example 4-4:

static Time( )
{
Name = "Time";
}

Notice that there is no access modifier (e.g.,
public) before the static constructor. Access
modifiers are not allowed on static constructors. In addition,
because this is a static member method, you cannot access nonstatic
member variables, and so Name must be declared a
static member variable:

private static string Name;

The final change is to add a line to DisplayCurrentTime(
), as in the following:

(Your output will vary depending on the date and time you run this
code.)

Although this code works, it is not necessary to create a static
constructor to accomplish this goal. You could, instead, use an
initializer:

private static string Name = "Time";

which accomplishes the same thing. Static constructors are useful,
however, for set-up work that cannot be accomplished with an
initializer and that needs to be done only once.

Javaprogrammerstakenote: In C#, a static constructor will serve
where a static initializer would be used in Java.

For example, assume you have an unmanaged bit of code in a legacy
DLL. You want to provide a class wrapper for this code. You can call
load library in your static constructor and initialize the jump table
in the static constructor. Handling legacy code and interoperating
with unmanaged code is discussed in Chapter 22.

4.3.3 Using Private Constructors

In C#,
there are no global methods or constants. You might find yourself
creating small utility classes that exist only to hold static
members. Setting aside whether this is a good design or not, if you
create such a class you will not want any instances created. You can
prevent any instances from being created by creating a default
constructor (one with no parameters), which does nothing, and which
is marked private. With no public constructors, it
will not be possible to create an instance of your class.[3]

[3] You can create a public static method that calls the
constructor and creates an instance of your class. Typically you
might use this idiom to ensure that only one instance of your class
ever exists. This is known as the Singleton design pattern, as
described in the seminal work Design Patterns by Gamma, et al.
(Addison Wesley).

4.3.4 Using Static Fields

A
common use of static member variables is to keep track of the number
of instances that currently exist for your class. Example 4-5 illustrates.

The Cat class has been stripped to its absolute
essentials. A static member variable called
instances is created and initialized to zero. Note
that the static member is considered part of the class, not a member
of an instance, and so it cannot be initialized by the compiler on
creation of an instance. Thus, an explicit initializer is
required for static member variables. When
additional instances of Cats are created (in a
constructor), the count is incremented.

Static Methods to Access Static Fields

It is undesirable to make member data public. This
applies to static member variables as well. One solution is to make
the static member private, as
we've done here with instances.
We have created a public accessor method, HowManyCats(
), to provide access to this private member.