Kapan konstruktor statis dipanggil dalam C #?

88

Ketika saya memiliki kelas yang berisi konstruktor statis, apakah konstruktor tersebut dipanggil saat rakitan yang berisi kelas tersebut pertama kali dimuat atau saat referensi pertama ke kelas tersebut dipukul?

Jason
sumber

Jawaban:

93

Saat kelas diakses untuk pertama kalinya.

Konstruktor Statis (Panduan Pemrograman C #)

Konstruktor statis digunakan untuk menginisialisasi data statis apa pun, atau untuk melakukan tindakan tertentu yang hanya perlu dilakukan sekali. Ini dipanggil secara otomatis sebelum contoh pertama dibuat atau anggota statis dirujuk.

Carra
sumber
6
Menarik bahwa dikatakan "sebelum contoh pertama dibuat atau anggota statis direferensikan". Ada beberapa kelonggaran di sana ketika itu benar-benar dipanggil.
Tim Barrass
6
@TimBalu karena beberapa persyaratan spesifikasi lainnya ternyata "sebelum" sebenarnya "segera sebelum" - lihat artikel Jon Skeet yang direferensikan di jawaban lain - stackoverflow.com/a/1437372/477420
Alexei Levenkov
A static constructor is used to initialize any static dataTIDAK. Lebih baik digunakan static initializeruntuk menginisialisasi hal-hal statis.
Yousha Aleayoub
41

Ini tidak sesederhana yang Anda harapkan meskipun ada dokumentasi yang jelas. Artikel Jon Skeet http://csharpindepth.com/Articles/General/Beforefieldinit.aspx membahas pertanyaan ini secara rinci.

Ringkasan:

Konstruktor statis dijamin akan dieksekusi segera sebelum referensi pertama ke anggota kelas itu - baik pembuatan instance atau metode / properti statis kelas itu sendiri.

Perhatikan bahwa initilaizer statis (jika tidak ada konstruktor statis) dijamin akan dijalankan kapan saja sebelum referensi pertama ke bidang tertentu.

Greg Beech
sumber
Artikel yang disebutkan sekarang ada di situs Jon Skeet: csharpindepth.com/Articles/General/Beforefieldinit.aspx
Sudhanshu Mishra
Berikut pertanyaan stackoverflow.com/questions/32525628/… mendemonstrasikan kasus ketika perilaku "langsung" cukup jelas.
Alexei Levenkov
1
Saya sebenarnya baru saja mengalami kasus di mana konstruktor statis dipanggil tepat sebelum metode Utama dari aplikasi konsol bahkan mulai dijalankan!
HerpDerpington
19

Konstruktor statis dipanggil sebelum Anda menggunakan apa pun di kelas, tetapi kapan tepatnya itu terjadi, terserah implementasinya.

Dijamin akan dipanggil sebelum anggota statis pertama diakses dan sebelum instance pertama dibuat. Jika kelas tidak pernah digunakan, konstruktor statis tidak dijamin akan dipanggil sama sekali.

Guffa
sumber
2
Ketika itu terjadi, jangan "sampai implementasi" jika implementasi itu mengikuti spesifikasi ECMA C #: "Eksekusi konstruktor statis dipicu oleh kejadian pertama berikut yang terjadi dalam domain aplikasi: [1] Sebuah instance dari kelas dibuat. [2] Setiap anggota statis kelas direferensikan. " (Bagian 17.11, ecma-international.org/publications/standards/Ecma-334.htm )
LukeH
1
@ Luke: "Waktu yang tepat dari eksekusi konstruktor statis bergantung pada implementasi" ondotnet.com/pub/a/dotnet/2003/07/07/staticxtor.html
Guffa
2
@ Guffa: Itu mungkin interpretasi penulis artikel, tetapi Anda tidak akan menemukan kata-kata itu di versi Microsoft atau ECMA / ISO dari spesifikasi C #.
LukeH
1

Jika metode statis dipanggil dari kelas induk, konstruktor statis tidak akan dipanggil, meskipun sudah ditentukan secara eksplisit. Berikut adalah contoh konstruktor b tidak dipanggil jika b.methoda () dipanggil.

static void Main(string[] args)
{
    b.methoda();
}

class a
{
    public static void methoda()
    {
        //using initialized method data
    }
}

class b : a
{
    static b()
    {
        //some initialization
    }
}    
Andrew
sumber
1

Tampaknya ada gotcha dengan konstruktor statis yang dijawab di tempat lain tetapi butuh beberapa saat untuk mencerna penjelasan sederhana. Semua dokumen dan penjelasan mengklaim konstruktor / intializer statis "dijamin" untuk dijalankan sebelum kelas pertama dibuat atau kolom statis pertama direferensikan. Gotcha masuk saat Anda mencoba untuk meletakkan singleton statis di kelas yang membuat instance dari dirinya sendiri (ayam / telur). Dalam kasus ini, konstruktor statis akhirnya dipanggil setelah konstruktor instans - dan dalam kasus saya, konstruktor instans berisi kode yang mengandalkan beberapa data statis.

Konstruktor statis dipanggil setelah konstruktor contoh?

Konstruktor statis dapat dijalankan setelah konstruktor non-statis. Apakah ini bug kompilator?

(jawaban bagi saya adalah meletakkan singleton di kelas terpisah atau secara manual menginisialisasi data statis di konstruktor instance sebelum diperlukan)

Etherman
sumber