C# Static

  • The static keyword refers to itself or standalone stuff instead of any objects or instances.
  • The span class="heavy">static keyword can be used with classes, fields, methods and constructors. It can also be used in properties, operators and events which will be introduced in later sections.
  • A constant or a defined type is implicitly a static member.
  • An instance cannot reference any static members hence this keyword cannot be used to reference a static member.

A static member can be accessed by the following format.

[Package Name].[Class Name].<Member Name>

The package name can be omitted if it is invoked in the same package or use using keyword.

The class name can be omitted if it is invoked in the same class.

Example 01-61-01

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using System;

namespace StaticFields
{
    public class Student
    {
        public string name;
        public int score;
    }

    public class MyClass
    {
        const int MAX = 50;
        public static int students;

        public static void Main()
        {
            Student s1 = new Student();
            s1.name = "Tom";
            s1.score = 90;
            MyClass.students++;

            Student s2 = new Student();
            s2.name = "Peter";
            s2.score = 80;
            students++;

            Student s3 = new Student();
            s3.name = "Sam";
            s3.score = 70;
            StaticFields.MyClass.students++;

            Console.WriteLine("Students in the class: {0}", students);
            Console.WriteLine("Maximum students allowed: {0}", MyClass.MAX);
            Console.Read();
        }
    }
}

Output

Students in the class: 3
Maximum students allowed: 50

Explanation

  • Line 5-9: Define a public class Student.
  • Line 11-37: Define a public class MyClass.
  • Line 13: Declare an integer constant MAX.
  • Line 14: Declare a static integer field students to hold the amount of the students in the class.
  • Line 16: Main method starts. Pay attention, the Main method is a static method which can only be defined in a class level.
  • Line 18-20: Create an instance of class Student and assign values to the fields.
  • Line 21: Increment the static field students by 1.
  • Line 26: It is the same as the statement in line 21 but the MyClass is omitted because students is defined in the same class.
  • Line 31: It is also the same as that in line 21. This time, the static field is referred in a full name.
  • Line 33: Output the value of the static field.
  • Line 34: Output the maximum students in a class. The constant is implicitly static so it can be referred by the class name.

Example 01-61-02

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;

namespace StaticMethods
{
    public class Circle
    {
        const double PI = 3.14;
        public double radius;

        public static void Main()
        {
            Circle c = new Circle();
            c.radius = 1.0;
            Console.WriteLine("Non-Static Method Area: {0}", c.getArea());
            Console.WriteLine("Static Method Area: {0}", getArea(10.0));
            Console.Read();
        }

        public static double getArea(double r)
        {
            //return getArea();
            return PI * r * r;
        }

        public double getArea()
        {
            //return getArea(this.radius);
            return PI * radius * radius;
        }

    }
}

Output

Non-Static Method Area: 3.14
Static Method Area: 314

Explanation

  • Line 5-31: Define a public class Circle.
  • Line 7: Declare a double constant PI.
  • Line 8: Declare a double field radius.
  • Line 10: Main method starts. The Main method is also a static method.
  • Line 12: Create an instance of class Circle.
  • Line 13: Assign 1.0 to the field radius.
  • Line 14: Output the non-static method c.getArea() defined in line 25-29.
  • Line 28: In the instance method, the area of the circel will be returned. PI is static implicitly and can be used in the instance method directly.
  • Line 15: Call a static method getArea(10.0) and the argument 10 is transferred to the parameter r in the method.
  • Line 19-23: Defined the static method. It also returns the area of the circle. Comparing the two getArea methods, one is a static method with one parameter. The other one is an instance method with no parameters and the instance field radius is used in the method directly.
  • Line 21: If the return statement in this line is used rather than that in line 22, You will get the following error message.

    An object reference is required for the non-static field, method, or property 'StaticMethods.Circle.getArea()'
    
    Because the non-static method cannot be invoked in a static method directly without an object reference.
  • Line 27: Remove // and comment out the code in line 28. Then run the program, you will get the same result. Because the static method is called and returns the result.
  • A static class cannot be instantiated so new keyword cannot be used to create an instance of a static class.
  • A static class can only have static members.
  • A static class is sealed and cannot be inherited by other classes.
  • A static class, like System.Math class, can only inherit from Object class directly.
  • A static class cannot have instance constructors because it cannot be instantiated.

Example 01-61-03

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
using System;

namespace StaticClass
{
    public static class Area
    {
        const double PI = 3.1416;

        public static double Rectangle(double length, double width)
        {
            return length * width;
        }

        public static double Triangle(double baseline, double height){
            return baseline * height / 2.0;
        }

        public static double Square(double side)
        {
            return Rectangle(side, side);
        }

        public static double Circle(double radius)
        {
            return PI * radius * radius;
        }
    }

    public class TestArea
    {
        public static void Main()
        {
            Console.WriteLine("Rectangle: length=10 width=10  Area={0}", Area.Rectangle(10, 10));
            Console.WriteLine("Triangle:  base=10   height=10 Area={0}", Area.Triangle(10, 10));
            Console.WriteLine("Square:    side=10             Area={0}", Area.Square(10));
            Console.WriteLine("Circle:    radius=10           Area={0}", Area.Circle(10));
            Console.Read();
        }
    }
}

Output

Rectangle: length=10 width=10  Area=100
Triangle:  base=10   height=10 Area=50
Square:    side=10             Area=100
Circle:    radius=10           Area=314.16

Explanation

  • Line 5-27: Define a public static class Area.
  • Line 9-12: Define a static method to calculate the area of a rectangle.
  • Line 14-16: Calculate the area of a triangle.
  • Line 18-21: Calculate the area of a square.
  • Line 20: Call Rectangle() method to get the area. This statement can be replaced with "return side * side;".
  • Line 23-26: Calculate the area of a circle and PI is a constant.
  • Line 29: Start the class TestArea.
  • Line 33-36: The static methods are called to output the areas of the shapes.

A static class is good to group a couple of related functions which are used directly in other classes. The good example of a static class is the predefined System.Math class which provides many mathematical functions. For example, the following statement will return the cosine of the specified angle.

double result = Math.Cos(angle);
  • A static constructor runs only once before the class is instantiated at first time so it is good to be used to initialize static fields or open a log file, etc.
  • A static constructor is defined without any parameters and access modifiers also it cannot be called directly.
  • Like static methods, a static constructor cannot access the non-static members of the class directly.

Example 01-61-04

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using System;

namespace StaticConstructor
{
    public class A
    {
        static A()
        {
            Console.WriteLine("Static constructor");
        }

        public A()
        {
            Console.WriteLine("Instance constructor");
        }
    }

    public class TestA
    {
        public static void Main()
        {
            Console.WriteLine("Before creating a1");
            A a1 = new A();
            Console.WriteLine("After creating a1");

            A a2 = new A();
            Console.WriteLine("After creating a2");
            Console.Read();
        }
    }
}

Output

Before creating a1
Static constructor
Instance constructor
After creating a1
Instance constructor
After creating a2

Explanation

  • Line 5-16: Define a public class A including only a static constructor and a non-static constructor.
  • Line 7-10: Define a static constructor to output a string to indicate if the constructor is invoked.
  • Line 12-15: Define a non-static constructor to compare with the static constructor.
  • Line 20: Start running Main() in TestA class.
  • Line 22: Output the string "Before creating a1".
  • Line 23: Create an instance a1. You can see the static constructor of class A was called first and then the non-constructor.
  • Line 24: Output a string before instantiating the class A at the second time.
  • Line 26: Create the second instance a2. This time the static constructor has never been called because it only runs once.
  • Line 27: Output the string.