Section 4.3. Using Static Members


4.3. Using Static Members

The members of a class (variables, methods, events, indexers, etc.) can be either instance members or static members. 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.[4] Suppose as well that the Button class has a static method SomeMethod(). To access the static method, you write:

[4] As noted earlier, btnUpdate and btnDelete are actually variables that refer to the unnamed instances on the heap. For simplicity we'll refer to these as the names of the objects, keeping in mind that this is just shorthand for "the name of the variables that refer to the unnamed instances on the heap."

Button.SomeMethod();

rather than:

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.

VB6 programmers take note: don't confuse the static keyword in C# with the Static keyword in VB6 and VB.NET. In VB, the Static keyword declares a variable that is available only 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 member. 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 don't 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.

In addition, static methods may be passed instance members as parameters (or may create such instances themselves within the static method). Because they are scoped to the class, instead of being scoped globally, they have access to the private members of the instances.

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 don't have a this reference, as there is no instance to point to.

Java programmers take note: in C#, calling static methods through instance variables is not permitted.


Static methods can't directly access nonstatic members. For Main() to call a nonstatic method, it must instantiate an object. Consider Example 4-2 shown earlier.

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 are guaranteed that the static constructor will run before any instance of your class is created.[5]

[5] Actually, the CLR guarantees to start running the static constructor before anything else is done with your class. However, it only guarantees to start running the static constructor; it doesn't actually guarantee to finish running it. It is possible to concoct a pathological case where two classes have a circular dependency on each other. Rather than deadlock, the CLR can run the constructors on different threads so that it meets the minimal guarantee of at least starting to run both constructors in the right order.

You can't 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 can't 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 aren't allowed on static constructors. In addition, because this is a static member method, you can't 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:

public void DisplayCurrentTime() {    System.Console.WriteLine("Name: {0}", Name);    System.Console.WriteLine("{0}/{1}/{2} {3}:{4}:{5}",        Month, Date, Year, Hour, Minute, Second); }

When all these changes are made, the output is:

Name: Time 11/27/2005 7:52:54 Name: Time 11/18/2005 11:45:30

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

Although this code works, it isn't necessary to create a static constructor to accomplish this goal. You can, instead, use an initializer:

private static string Name = "Time";

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

Java programmers take note: 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 LoadLibrary 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. Static Classes

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, if you create such a class you won't want any instances created. Mark your class Static to ensure that no instance of the class may be created. Static classes are sealed , and thus you may not create derived types of a Static class. Note, however, that static classes may not contain nonstatic members or have a constructor.

4.3.4. Using Static Fields

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

Example 4-5. Using static fields for instance counting
#region Using directives using System; using System.Collections.Generic; using System.Text; #endregion namespace StaticFields {    public class Cat    {       private static int instances = 0;       public Cat( )       {          instances++;       }       public static void HowManyCats( )       {          Console.WriteLine( "{0} cats adopted",                instances );       }    }    public class Tester    {       static void Main( )       {          Cat.HowManyCats( );          Cat frisky = new Cat( );          Cat.HowManyCats( );          Cat whiskers = new Cat( );          Cat.HowManyCats( );       }    } } Output: 0 cats adopted 1 cats adopted 2 cats adopted

The Cat class has been stripped to its absolute essentials. A static member variable called instances is created and initialized to 0. Note that the static member is considered part of the class, not a member of an instance, and so it can't be initialized by the compiler on creation of an instance. Thus, if you want to initialize a static member, you must provide an explicit initializer. 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.




Programming C#(c) Building. NET Applications with C#
Programming C#: Building .NET Applications with C#
ISBN: 0596006993
EAN: 2147483647
Year: 2003
Pages: 180
Authors: Jesse Liberty

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