статический полевой инициализатор только для чтения по сравнению со статической инициализацией конструктора

Ниже два различных способа инициализировать статические поля только для чтения. Существует ли различие между двумя подходами? Если да, когда нужно быть предпочтен по другому?

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;
    }
}
37
задан CZoellner 26 October 2016 в 13:52
поделиться

2 ответа

Есть одно тонкое различие между этими двумя, которое можно увидеть в коде IL - добавление явного статического конструктора сообщает компилятору C # не отмечать тип как beforefieldinit . Параметр beforefieldinit влияет на запуск инициализатора типа, и знание этого полезно, например, при написании ленивых синглтонов на C # .

Вкратце разница заключается в следующем:

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

Во всех других аспектах они одинаковы. Вывод отражателя:

Класс 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
} 

Класс 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    
}
35
ответ дан 27 November 2019 в 04:48
поделиться

По сути, они одинаковы, но если у вас есть и назначение только для чтения статическому полю и конструктор статического типа, сначала выполняется присвоение только для чтения.

7
ответ дан 27 November 2019 в 04:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: