Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic static fields initialization

I'm just getting curious about the following code :

public static class Container<T>
{
    public static readonly T[] EmptyArray = new T[0];
}

As I've understood the static class Container will be initialized when the following code executes:

...
var emptyArray = Container<int>.EmptyArray;
...

Am I right ? Any explanations on static generic classes/members initialization would be appreciated. Thanks in advance.

like image 394
danyloid Avatar asked Sep 16 '11 00:09

danyloid


People also ask

How do you initialize a static field?

The only way to initialize static final variables other than the declaration statement is Static block. A static block is a block of code with a static keyword. In general, these are used to initialize the static members. JVM executes static blocks before the main method at the time of class loading.

Can generic variables be static?

Using generics, type parameters are not allowed to be static. As static variable is shared among object so compiler can not determine which type to used. Consider the following example if static type parameters were allowed.

Can static variables be initialized?

A static variable in a block is initialized only one time, prior to program execution, whereas an auto variable that has an initializer is initialized every time it comes into existence. A static object of class type will use the default constructor if you do not initialize it.

Is static variable initialization necessary?

Static variables are initialized only once. Compiler persist the variable till the end of the program. Static variable can be defined inside or outside the function. They are local to the block.


2 Answers

The guarantee is that the static field is initialized before you access it. (And also, if there is also a static constructor, then all static fields will be initialized before the static constructor is run.)

For generic classes, static initialization works on a per-type basis, so Container<int> acts as if it is a completely different class to Container<double>. This is actually true for all static parts of a generic class - each type gets its own 'copy'.

An example will show this last point more clearly:

static class Foo<T>
{
    static int count = 0;
    public static int Increment()
    {
        return ++count;
    }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(Foo<int>.Increment());
        Console.WriteLine(Foo<int>.Increment());
        Console.WriteLine(Foo<double>.Increment());
    }
}

Output:

1
2
1
like image 107
porges Avatar answered Sep 28 '22 00:09

porges


Static field initializers are really moved into the static constructor (type initializer) of the class. So your code compiles into this automagically:

public static class Container<T>
{
    public static readonly T[] EmptyArray;

    static Container()
    {
        EmptyArray = new T[];
    }
}

From MSDN about static constructors:

It [Static Constructor] is called automatically before the first instance is created or any static members are referenced.

Since Container<string> and Container<bool> are not the same, the static constructor is called once for each type of T.

like image 20
vcsjones Avatar answered Sep 28 '22 00:09

vcsjones