Beforefieldinit flag ne işe yarar?


82

Beforefieldinit bayrağı ne işe yarar? Sınıfımın bilgi düzeyine baktığımda bu bayrağı görüyorum ama bu bayrağın gerçekte ne yaptığını bilmiyorum?

Yanıtlar:


132

Bkz yazımda bu çok konuda.

Temel olarak, beforefieldinit"tür, herhangi bir statik alana başvurulmadan önce herhangi bir noktada başlatılabilir" anlamına gelir. Teoride bu, çok tembel olarak başlatılabileceği anlamına gelir - herhangi bir alana dokunmayan statik bir yöntem çağırırsanız, JIT'in türü başlatması gerekmez.

Pratikte bu sınıf var demektir önceki başka türlü olurdu daha - bu ilk yöntemin başlangıcında başlatılması için tamam olabilir kullanabilirsiniz. Bunu kendilerine beforefieldinituygulanmamış türlerle karşılaştırın , burada tür başlatmanın ilk gerçek kullanımdan hemen önce gerçekleşmesi gerekir .

Diyelim ki bizde:

public static void DoSomething(bool which)
{
    if (which)
    {
        FirstType.Foo();
    }
    else
    {
        SecondType.Bar();
    }
}

Her iki tür de beforefieldinitbunlara uygulanmışsa (bu, türün statik bir kurucusu olmadığı sürece varsayılan olarak C # yaparlar), o zaman ikisi de DoSomethingyöntemin başlangıcında başlatılır (genellikle - garanti edilmez). Eğer yoksa , bayrağa bağlı olarak bunlardan beforefieldinitsadece biri başlatılacaktır.

Bu nedenle , tekil kalıbı uygularken statik bir kurucu (hatta boş bile!) Kullanmak yaygındır .


"tür, herhangi bir alana başvurulmadan önce herhangi bir noktada başlatılabilir." statik yöntemler çalıştırmak için de doğru mu?
Royi Namir

@RoyiNamir, CLI spesifikasyonu, BeforeFieldInit uygulanırsa "türün başlatıcı yöntemi, bu tür için tanımlanan herhangi bir statik alana ilk erişimde veya daha önce çalıştırılır" der. Bu öznitelik eksikse (statik .ctor), "önce bu türdeki herhangi bir statik veya örnek alana erişim veya bu türdeki herhangi bir statik, örnek veya sanal yöntemin ilk çağrısı". Bu nedenle, statik yöntem başka bir statik alana başvurmadıkça, uygulanan BeforeFieldInit için doğru değildir.
Arman

3
Statik kurucuları (yani beforefieldinit bayrağına sahip olmayan sınıflar) kullanmanın bir performans cezası olduğunu keşfettim. Belirli bir sınıfın statik üyelerini sık sık çağırırsanız, türün henüz başlatılıp başlatılmadığını test etmek için çalışma zamanının her çağrıdan önce fazladan bir kontrol yapması gerektiği anlaşılır; beforefieldinit bu kontrollerden kaçınır. Birkaç kıyaslama, beforefieldinit ile yaklaşık% 50 daha hızlıydı: codeproject.com/Articles/87991/…
Qwertie

6

4.6'da değişecek gibi görünüyor

https://github.com/dotnet/coreclr/issues/1193


Harika, yani bu, alanı başlatmak için son ana kadar bekleyeceği anlamına mı geliyor (sahip olup olmadığına bakılmaksızın beforefieldinit)?
James Ko

1
İlk kullanımdan önce, tüm erişimlerin önüne başlatma kontrolü getirilecektir. Bundan sonra, diğer yöntemler karıştırıldığında, üretilen kod alana doğrudan erişecektir. İlkel tipte ise, o zaman bir JIT zaman sabiti olarak bile kullanılabilir.
OmariO

2
Jon'un .Net 4.0'dan başlayarak tür başlatma değişikliklerine ilişkin ayrıntılı analizi burada .
RBT
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.