Static Members


Both fields and methods of a class may be declared as static. Static members are shared amongst instances of a class. For example, consider the following sample.

// Static1 - A Static Field

using System;

class X
{
    public static int i;                    // static field - shared

    public void Set(int ii) { i = ii; }     // non-static method
}

class TestStatic
{
    public static void Main()
    {
        X x = new X();
        x.Set(10);

        X y = new X();
        y.Set(20);

        Console.WriteLine("X.i = {0}", X.i);
    }
}

The output of the program is shown below.

X.i = 20

The static member i of class X is shared amongst all instances of the class X. Non-static methods may access the static member, as shown by the method X.Set. In the main routine, an instance of X (called x) is first created. The method X.Set is called for this instance and it sets the static member i to 10. Another instance of X (called y) is created and it in turn also calls X.Set, setting the value of i to 20. Next the static member is written to the console. Note carefully, the form of this statement.

Console.WriteLine("X.i = {0}", X.i);

The static member i of X is referred to as X.i. This is not the usual syntax for referring to non-static members, which would be:

object.member-name

rather than:

class-name.member-name

which is the way it is done in the sample. Static members are referred to as class-name.member-name and this applies to both fields and methods. The syntax is possible because there is only one field i for the class X above. Therefore, X.i uniquely identifies the static field. Note also that for the above sample, object-name.member-name (i.e. x.i or y.i) is not allowed. So the statement:

Console.WriteLine("X.i = {0}", X.i);

cannot be replaced with the following statement.

Console.WriteLine("y.i = {0}", y.i);

In the above sample, the static field i was first set to 10 and then set to 20 through different instances of the class X. Even though different instances were used, the value 20 overwrote the value 10, which is to be expected because i is shared amongst instances. Ultimately, X.i printed out as 20.

Non-static fields of a class may be referred to as instance variables because each instance of the class has its own copy of the field. Clearly, a static field of a class is not an instance variable because it is shared amongst all instances.

Static Methods

Methods can also be static, which means that a method can be shared amongst instances of a class. The maths function Math.Abs is a static member of the class Math. It is accessed in the following fashion.

double d = -10.5;
double a = Math.Abs(d);   // Yields 10.5

There are quite a few maths functions defined statically in the class Math. Sin, Cos, Tan, Sinh, Cosh, Tanh, Log etc are all defined as static functions of the class Math. An example of calling Math.Sin is shown below.

double pi=3.14159265358979323846;
double s = Math.Sin(pi/6);

When considering how to design a complex number class, it is possible to design methods such as Abs and Sin as non-static methods; however, to be consistent with the maths library it is convenient to define Abs and Sin as static members of the class Complex. That way, they have a similar invocation syntax to their real counterparts. This gives rise to the next example - the beginnings of a complex number class.

Before displaying the code, it is useful to note that the absolute value of a complex number is its distance from the origin. For z = x+iy; by Pythagoras' theorem this yields.

Abs(z) = Math.Sqrt(z.x * z.x + z.y * z.y)

Here is the beginnings of the class Complex.

// Static2 - A Static Method

using System;

public struct Complex
{
    public double x;
    public double y;

    public Complex(double x_set) { x = x_set; y = 0; }

    public Complex(double x_set, double y_set) { x = x_set; y = y_set; }

    public Complex(Complex copy) { x = copy.x; y = copy.y; }

    public static double Abs(Complex z) { return Math.Sqrt(z.x * z.x + z.y * z.y); }
}

class Test
{
    public static void Main()
    {
        Complex z = new Complex(3, 4);
        double abs = Complex.Abs(z);
        Console.WriteLine("Abs(3+4i) = {0}", abs);
    }
}

Exercise

Given that the sine, cosine, hyperbolic sine and hyperbolic cosine of a complex number are calculated via the formulae:

cos(z)  = cos(x) * cosh(y) - i * sin(x) * sinh(y)
cosh(z) = cosh(x) * cos(y) + i * sinh(x) * sin(y)
sin(z)  = sin(x) * cosh(y) + i * cos(x) * sinh(y)
sinh(z) = sinh(x) * cos(y) + i * cosh(x) * sin(y)

update the class Complex (above) to contain the required static methods. Each of the required real valued functions are found in the library class Math. The answer may be found in the project Static3.

There are several restrictions that apply to static methods:

  1. a static method does not have a this reference,
  2. a static method cannot call a non-static method directly,
  3. a static method can only access static data (and cannot access instance variables directly).

Despite the above, a static method can access methods and instance variables if it does so though an object reference with the dot operator.

Static Constructors

A single, parameterless constructor can be specified as static. A static constructor is typically used to initialize data that applies to the class as a whole rather than to any particular instance of the class. A static constructor is called prior to the first object of the class being created. Consider the following example.

// Static4 - A Static Method

using System;

public class X
{
    public static int i;
    public int j;

    static X()    // static constructor
    {
        i = 50;
        Console.WriteLine("Inside Static Constructor");

    }

    public X()    // Non-static constructor
    {
        j = 100;
        Console.WriteLine("Inside Non-Static Constructor");
    }
}


class TestStatic
{
    public static void Main()
    {
        X x = new X(); // Calls both static and non-static constructors
        X y = new X(); // Calls only the non-static constructor
    }
}

The output of the program is shown below.

Inside Static Constructor
Inside Non-Static Constructor
Inside Non-Static Constructor

From the output it is apparent that the static constructor is called only once - when the first object is being created. The second object that is created only calls the non-static constructor.

Static Classes

A static class is a class:

  1. where no object of the static class can be created and
  2. which contains only static members.

The syntax for creating a static class is shown below.

static class class-name
{
 ...
}

A static class cannot have instance constructors, but it can have a static constructor.