Pregunta

A continuación se presentan dos maneras diferentes para inicializar los campos de sólo lectura estática. ¿Hay alguna diferencia entre los dos enfoques? En caso afirmativo, ¿Cuándo se debe preferirse sobre el 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;
    }
}
¿Fue útil?

Solución

Hay una diferencia sutil entre estos dos, que se puede ver en el código IL - poner un constructor estático explícita indica al compilador de C # no marcar el tipo beforefieldinit . El beforefieldinit afecta cuando el tipo de inicialización se ejecuta y saber acerca de esto es útil cuando se escriben únicos perezosos en C # , por ejemplo.

En resumen, la diferencia es la siguiente:

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

En todos los demás aspectos que son los mismos. La salida del 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    
}

Otros consejos

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

En el caso de una inicialización constructor estático explícita, la inicialización del miembro estático sucede en el momento que se accede al tipo. En el ejemplo dado en el caso de la clase A, la inicialización sólo ocurrirá cuando connectionString se refiere en primer lugar, mientras que en caso de la clase B de inicialización que va a pasar la primera vez que se refiere a la clase de tipo B, no necesariamente acceder connectionString .

Sólo C # (.NET 4.0) proporciona control sobre cómo nos miembros estáticos se pueden inicializar. Con VB.NET sólo el método no beforefieldinit es posible mientras que con C ++ / CLI sólo el beforefieldinit mecanismo es posible.

Son esencialmente el mismo, pero si le sucede que tiene ambos una asignación de sólo lectura a un campo estático y un tipo estático constructor, la asignación de sólo lectura ocurra primero.

Tengo que añadir que, con explícita constructor presente (versión no beforefieldinit) accediendo a los miembros estáticos son comparativamente manera más lenta.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top