Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

static readonly field initializer vs static constructor initialization

Below are two different ways to initialize static readonly fields. Is there a difference between the two approaches? If yes, when should one be preferred over the other?

class A {     private static readonly string connectionString =         WebConfigurationManager.ConnectionStrings["SomeConnection"].ConnectionString; }  class B {     private static readonly string connectionString;      static B()     {         connectionString =             WebConfigurationManager.ConnectionStrings["SomeConnection"].ConnectionString;     } } 
like image 451
stackoverflowuser Avatar asked May 03 '10 21:05

stackoverflowuser


People also ask

What is the difference between static readonly and constant?

Constant and ReadOnly keyword is used to make a field constant which value cannot be modified. The static keyword is used to make members static that can be shared by all the class objects.

What is difference between static constructor and private constructor?

Static constructor will be called first time when the class is referenced. Static constructor is used to initialize static members of the class. In the non static class the private or public constructor will not be called. Static members will not be initialized either by private or public constructor.

Can readonly be set in constructor?

You can initialize a ReadOnly property in the constructor or during object construction, but not after the object is constructed.

Which constructor is called first in C# static or default?

A static constructor is called automatically. It initializes the class before the first instance is created or any static members declared in that class (not its base classes) are referenced. A static constructor runs before an instance constructor.


2 Answers

There is one subtle difference between these two, which can be seen in the IL code - putting an explicit static constructor tells the C# compiler not to mark the type as beforefieldinit. The beforefieldinit affects when the type initializer is run and knowing about this is useful when writing lazy singletons in C#, for example.

In brief the difference is this:

.class private auto ansi beforefieldinit A .class private auto ansi B 

In all other aspects they are the same. Output from Reflector:

Class A:

.class private auto ansi beforefieldinit A     extends [mscorlib]System.Object {     .method private hidebysig specialname rtspecialname static void .cctor() cil managed     {         .maxstack 8         L_0000: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2<string, class Connection> WebConfigurationManager::ConnectionStrings         L_0005: ldstr "SomeConnection"         L_000a: callvirt instance !1 [mscorlib]System.Collections.Generic.Dictionary`2<string, class Connection>::get_Item(!0)         L_000f: ldfld string Connection::ConnectionString         L_0014: stsfld string A::connectionString         L_0019: ret      }      .method public hidebysig specialname rtspecialname instance void .ctor() cil managed     {         .maxstack 8         L_0000: ldarg.0          L_0001: call instance void [mscorlib]System.Object::.ctor()         L_0006: ret      }      .field private static initonly string connectionString }  

Class B:

.class private auto ansi B     extends [mscorlib]System.Object {     .method private hidebysig specialname rtspecialname static void .cctor() cil managed     {         .maxstack 8         L_0000: nop          L_0001: ldsfld class [mscorlib]System.Collections.Generic.Dictionary`2<string, class Connection> WebConfigurationManager::ConnectionStrings         L_0006: ldstr "SomeConnection"         L_000b: callvirt instance !1 [mscorlib]System.Collections.Generic.Dictionary`2<string, class Connection>::get_Item(!0)         L_0010: ldfld string Connection::ConnectionString         L_0015: stsfld string B::connectionString         L_001a: ret  }      .method public hidebysig specialname rtspecialname instance void .ctor() cil managed     {         .maxstack 8         L_0000: ldarg.0          L_0001: call instance void [mscorlib]System.Object::.ctor()         L_0006: ret      }       .field private static initonly string connectionString     } 
like image 64
Mark Byers Avatar answered Sep 22 '22 08:09

Mark Byers


The beforefieldinit attribute indicates how the initialization happens.

In case of an explicit static constructor initialization, the initialization of the static member happens the moment the type is accessed. In the example given in case of class A, the initialization will happen only when connectionString is first referred, whereas in case of class B initialization will happen the first time the type class B is referred, not necessarily accessing connectionString.

Only C# (.NET 4.0 ) provides us control over how static members can be initialized. With VB.NET only the non beforefieldinit method is possible whereas with C++/CLI only the beforefieldinit mechanism is possible.

like image 23
Swami PR Avatar answered Sep 22 '22 08:09

Swami PR