TheDeveloperBlog.com


C# Static Field

Static field. A static field is not attached to an instance. It does not depend on an instance expression. This means it requires one fewer level of indirection on each load and store. Instance fields result in more instructions being executed.


Example. First, this program increments instance fields and static fields. It tests how performance is affected when an instance field is accessed because the instance expression ("this") must be evaluated.

Int TypePreincrement Integers

Tip: Static fields are simpler because they do not require that extra level of indirection. This is reflected in better performance.

This Instance
C# program that tests static fields

using System;
using System.Diagnostics;

class Test1
{
    int _a; // Instance fields:
    int _b;
    int _c;
    public void X()
    {
	this._a++; // Change instance field values:
	this._b++;
	this._c++;
    }
}

class Test2
{
    static int _a; // Static fields:
    static int _b;
    static int _c;
    public void X()
    {
	_a++; // Change static field values:
	_b++;
	_c++;
    }
}

class Program
{
    const int _max = 200000000;
    static void Main()
    {
	Test1 test1 = new Test1(); // Instantiate instance fields
	Test2 test2 = new Test2(); // Instantiate

	var s1 = Stopwatch.StartNew();
	for (int i = 0; i < _max; i++)
	{
	    test1.X(); // Instance fields:
	    test1.X();
	    test1.X();
	    test1.X();
	    test1.X();
	}
	s1.Stop();
	var s2 = Stopwatch.StartNew();
	for (int i = 0; i < _max; i++)
	{
	    test2.X(); // Static fields:
	    test2.X();
	    test2.X();
	    test2.X();
	    test2.X();
	}
	s2.Stop();
	Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000 * 1000) /
	    _max).ToString("0.00") + " ns");
	Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000 * 1000) /
	    _max).ToString("0.00") + " ns");
	Console.Read();
    }
}

Output

10.51 ns  (Time for instance field usage)
10.21 ns  (Time for static field usage)

Test1 and Test2 are similar. The Test1 class, however, has instance fields while the Test2 class has static fields. If you create many Test1 class instances, each will have its own copy of the fields.

And: If you create many Test2 instances, there will only be one copy of the fields in it.

Note: The instance method on the classes mutates the value of the fields. The Program class simply runs a benchmark of the two X methods.

When executed, this program will change the value of the instance fields in Test1 through the method X. It will then change the value of the static fields located inside the Test2 declaration through the other method X.

Typically: The Test2.X method is slightly faster on my computer, by about 0.3 nanoseconds per loop iteration.

Result: Evaluating the instance expression for the instance fields in Test1 causes a slowdown over the static fields in Test2.

BenchmarkOptimizations

Example 2. Next, a static field does not have to be a value type. It can instead be a reference. The reference is initialized automatically to null. We can assign it to a new instance of the object, and use it throughout the program.

Here: We use a static reference field to point to a new instance of the custom Test class, declared in the same file.

C# program that uses static class instance

using System;

class Test
{
    public int _value;
}

class Program
{
    static Test _field;

    static void Main()
    {
	// Assign static field to new object instance.
	Program._field = new Test();

	// Assign an instance field of the object.
	Program._field._value = 1;

	// Display value.
	Console.WriteLine(Program._field._value);
    }
}

Output

1


IL. An instance field is one that can be created many times in the environment, while a static field exists only in one place. To evaluate an instance field, the instance expression must first be evaluated.

Tip: In the intermediate language, the instance expression is equal to the first argument to an instance method.

Intermediate Language

When accessing an instance field, the instance expression is loaded onto the evaluation stack with "ldarg.0". This step is not required for a static field—the static field does not require that extra level of indirection.

Therefore: Using instance fields will insert an additional instruction into the IL for accesses, both reads and writes.


Discussion. The consideration of static and instance field performance is not the primary one to make in nontrivial programs. If you need instances of a type, then please use instance fields as they will make your program correct.

However: The point here was to examine the evaluation process for instance fields and compare it to that of static fields.

Tip: You can sometimes change instance fields to static fields for performance improvements.


Summary. We looked at the evaluation and performance of static fields and instance fields. Instance fields must first have the instance expression evaluated. Static fields are global and do not need this extra evaluation.

Therefore: Static fields are faster but should only be used when they are correct in programs.