Aracılığıyla paylaş


Statik Oluşturucular (C# Programlama Kılavuzu)

Statik oluşturucu, statik verileri başlatmak veya yalnızca bir kez gerçekleştirilmesi gereken belirli bir eylemi gerçekleştirmek için kullanılır. İlk örnek oluşturulmadan veya statik üyelere başvurulmadan önce otomatik olarak çağrılır. Statik oluşturucu en fazla bir kez çağrılır.

class SimpleClass
{
    // Static variable that must be initialized at run time.
    static readonly long baseline;

    // Static constructor is called at most one time, before any
    // instance constructor is invoked or member is accessed.
    static SimpleClass()
    {
        baseline = DateTime.Now.Ticks;
    }
}

Statik başlatmanın parçası olan birkaç eylem vardır. Bu eylemler aşağıdaki sırayla gerçekleştirilir:

  1. Statik alanlar 0 olarak ayarlanır. Çalışma zamanı genellikle bu başlatmayı yapar.
  2. Statik alan başlatıcıları çalışır. En türetilmiş türdeki statik alan başlatıcıları çalıştırılır.
  3. Temel tür statik alan başlatıcıları çalışır. Doğrudan tabandan başlayarak, her taban türü aracılığıyla System.Object'ya kadar olan statik alan başlatıcıları.
  4. Tüm statik oluşturucular çalışır. Her bir temel sınıfın nihai alt sınıfından türetilmiş her tür için tüm statik oluşturucular çalıştırılır. Statik oluşturucu yürütme sırası belirtilmemiş. Ancak, hiyerarşideki tüm statik oluşturucular herhangi bir örnek oluşturulmadan önce çalışır.

Önemli

Bir statik oluşturucunun herhangi bir örnek oluşturulmadan önce çalışması kuralında önemli bir özel durum vardır. Statik alan başlatıcı türün bir örneğini oluşturursa, bu başlatıcı statik oluşturucu çalışmadan önce (örnek oluşturucuya yapılan herhangi bir çağrı dahil) çalışır. En yaygın olarak, aşağıdaki örnekte gösterildiği gibi singleton deseninde görülür.

public class Singleton
{
    // Static field initializer calls instance constructor.
    private static Singleton instance = new Singleton();

    private Singleton()
    { 
        Console.WriteLine("Executes before static constructor.");
    }

    static Singleton()
    { 
        Console.WriteLine("Executes after instance constructor.");
    }

    public static Singleton Instance => instance;
}

Modül başlatıcı , statik bir oluşturucuya alternatif olabilir. Daha fazla bilgi için bkz. modül başlatıcıları için belirtim.

Açıklamalar

Statik oluşturucular aşağıdaki özelliklere sahiptir:

  • Statik oluşturucu erişim değiştiricileri almaz veya parametreleri yoktur.
  • Bir sınıf veya yapı yalnızca bir statik oluşturucuya sahip olabilir.
  • Statik oluşturucular devralınamaz veya aşırı yüklenemez.
  • Statik oluşturucu doğrudan çağrılamıyor ve yalnızca ortak dil çalışma zamanı (CLR) tarafından çağrılmak üzere tasarlanıyor. Otomatik olarak çağrılır.
  • Kullanıcının, statik oluşturucunun programda ne zaman yürütülürken denetimi yoktur.
  • Statik oluşturucu otomatik olarak çağrılır. İlk örnek oluşturulmadan önce sınıfı başlatır veya bu sınıfta bildirilen statik üyelere (temel sınıflarına değil) başvurulur. Statik oluşturucu, örnek oluşturucudan önce çalışır. Statik alan değişkeni başlatıcıları statik oluşturucunun sınıfında mevcutsa, sınıf bildiriminde göründükleri metin sırasına göre çalışırlar. Başlatıcılar statik oluşturucudan hemen önce çalışır.
  • Statik alanları başlatmak için statik bir oluşturucu sağlamazsanız, tüm statik alanlar C# türlerinin Varsayılan Değerleri'nde listelendiği gibi varsayılan değerlerine başlatılır.
  • Statik bir oluşturucu özel durum oluşturursa, çalışma zamanı bunu ikinci kez çağırmaz ve uygulama etki alanının ömrü boyunca tür başlatılmamış olarak kalır. En yaygın olarak, statik oluşturucu bir TypeInitializationException istisnası fırlatır, ya bir türü örnekleyemediğinde ya da statik oluşturucu içinde meydana gelen işlenmemiş bir istisna için. Kaynak kodunda açıkça tanımlanmayan statik oluşturucular için sorun giderme, ara dil (IL) kodunun incelenmesini gerektirebilir.
  • Statik bir oluşturucunun varlığı tür özniteliğinin eklenmesini BeforeFieldInit engeller. Bu, çalışma zamanı iyileştirmeyi sınırlar.
  • olarak static readonly bildirilen bir alan yalnızca bildiriminin bir parçası olarak veya statik bir oluşturucuda atanabilir. Açık bir statik yapıcı gerekli olmadığında, daha iyi bir çalışma zamanı optimizasyonu için statik bir yapıcı yerine, bildirim sırasında statik alanları başlatın.
  • Çalışma zamanı, tek bir uygulama etki alanında en fazla bir kez statik oluşturucu çağırır. Bu çağrı, sınıfın belirli türüne göre kilitli bir bölgede yapılır. Statik bir oluşturucunun gövdesinde fazladan kilitleme mekanizması gerekmez. Kilitlenme riskini önlemek için statik oluşturucularda ve başlatıcılarda geçerli iş parçacığını engellemeyin. Örneğin, görevler, iş parçacıkları, bekleme tutamaçları veya olaylar için beklemeyin, kilitleri edinmeyin ve paralel döngüler Parallel.Invoke ve Paralel LINQ sorguları gibi engelleyici paralel işlemleri yürütmeyin.

Not

Doğrudan erişilebilir olmasa da, başlatma özel durumlarının giderilmesine yardımcı olmak için açık bir statik oluşturucunun varlığı belgelenmelidir.

Kullanım

  • Statik oluşturucuların tipik bir kullanımı, sınıfın bir günlük dosyası kullanması ve oluşturucunun bu dosyaya girdi yazmak için kullanılmasıdır.
  • Statik oluşturucular, LoadLibrary yöntemini çağırmanın mümkün olduğu durumlarda, yönetilmeyen kod için sarmalayıcı sınıfları oluştururken de yararlıdır.
  • Statik oluşturucular, tür parametresi kısıtlamaları aracılığıyla derleme zamanında denetlenmeyen tür parametresinde çalışma zamanı denetimlerini zorunlu kılmak için de uygun bir yerdir.

Örnek

Bu örnekte, sınıfın Bus statik bir oluşturucus vardır. öğesinin ilk örneği Bus oluşturulduğunda ()bus1 sınıfını başlatmak için statik oluşturucu çağrılır. Örnek çıktı, iki Bus örneği oluşturulsa bile statik yapıcının yalnızca bir kez çalıştığını ve örnek yapıcı çalışmadan önce çalıştığını doğrular.

public class Bus
{
    // Static variable used by all Bus instances.
    // Represents the time the first bus of the day starts its route.
    protected static readonly DateTime globalStartTime;

    // Property for the number of each bus.
    protected int RouteNumber { get; set; }

    // Static constructor to initialize the static variable.
    // It is invoked before the first instance constructor is run.
    static Bus()
    {
        globalStartTime = DateTime.Now;

        // The following statement produces the first line of output,
        // and the line occurs only once.
        Console.WriteLine($"Static constructor sets global start time to {globalStartTime.ToLongTimeString()}");
    }

    // Instance constructor.
    public Bus(int routeNum)
    {
        RouteNumber = routeNum;
        Console.WriteLine($"Bus #{RouteNumber} is created.");
    }

    // Instance method.
    public void Drive()
    {
        TimeSpan elapsedTime = DateTime.Now - globalStartTime;

        // For demonstration purposes we treat milliseconds as minutes to simulate
        // actual bus times. Do not do this in your actual bus schedule program!
        Console.WriteLine($"{this.RouteNumber} is starting its route {elapsedTime.Milliseconds:N2} minutes after global start time {globalStartTime.ToShortTimeString()}.");
    }
}

class TestBus
{
    static void Main()
    {
        // The creation of this instance activates the static constructor.
        Bus bus1 = new Bus(71);

        // Create a second bus.
        Bus bus2 = new Bus(72);

        // Send bus1 on its way.
        bus1.Drive();

        // Wait for bus2 to warm up.
        System.Threading.Thread.Sleep(25);

        // Send bus2 on its way.
        bus2.Drive();

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Sample output:
    Static constructor sets global start time to 3:57:08 PM.
    Bus #71 is created.
    Bus #72 is created.
    71 is starting its route 6.00 minutes after global start time 3:57 PM.
    72 is starting its route 31.00 minutes after global start time 3:57 PM.
*/

C# dili belirtimi

Daha fazla bilgi için C# dil belirtiminin Statik oluşturucular bölümüne bakın.

Ayrıca bkz.