referencia propiedad modificador metodo codigos c# c#-3.0 c#-2.0 initializer static-constructor

c# - propiedad - iniciador de campo de solo lectura estático vs inicialización de constructor estático



static c# (3)

A continuación hay dos maneras diferentes de inicializar campos estáticos de solo lectura. ¿Hay alguna diferencia entre los dos enfoques? En caso afirmativo, ¿cuándo se debe preferir uno al otro?

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; } }


El atributo beforefieldinit indica cómo ocurre la inicialización.

En el caso de una inicialización explícita del constructor estático, la inicialización del miembro estático ocurre en el momento en que se accede al tipo. En el ejemplo dado en el caso de la clase A, la inicialización ocurrirá solo cuando connectionString se refiera por primera vez, mientras que en el caso de la clase B la inicialización se producirá la primera vez que se haga referencia a la clase de tipo B, no necesariamente accediendo a connectionString .

Solo C # (.NET 4.0) nos proporciona control sobre cómo pueden inicializarse los miembros estáticos. Con VB.NET, solo es posible el método sin antes del campo , mientras que con C ++ / CLI solo es posible el mecanismo de antes del inicio del campo .


En esencia, son lo mismo, pero si tiene una asignación de solo lectura para un campo estático y un constructor de tipo estático, la asignación de solo lectura ocurre primero.


Hay una sutil diferencia entre estos dos, que se puede ver en el código IL: poner un constructor estático explícito le dice al compilador C # que no marque el tipo como beforefieldinit . El campo anterior afecta cuando se ejecuta el inicializador de tipo y conocer esto es útil cuando se escriben singletons perezosos en C # , por ejemplo.

En resumen, la diferencia es esta:

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

En todos los otros aspectos, son lo mismo. Salida de Reflector:

Clase 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 }

Clase 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 }