Megosztás a következőn keresztül:


Statikus konstruktorok (C# programozási útmutató)

A statikus konstruktorok bármely statikus adat inicializálására vagy egy olyan művelet végrehajtására szolgálnak, amelyet csak egyszer kell végrehajtani. A rendszer automatikusan meghívja az első példány létrehozása előtt, vagy bármely statikus tagra hivatkozik. A statikus konstruktorok legfeljebb egyszer lesznek meghívva.

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;
    }
}

A statikus inicializálásnak több művelet is része. Ezek a műveletek a következő sorrendben történnek:

  1. A statikus mezők értéke 0. Ezt általában a futtatókörnyezet végzi.
  2. A statikus mező inicializálói futnak. A statikus mező inicializálói a legelterjedtebb típusban futnak.
  3. Az alaptípusú statikus mező inicializálói futnak. Statikus mező inicializálói a közvetlen alaptól kezdve az egyes alaptípusokon át a következőig System.Object: .
  4. Az alap statikus konstruktorok futnak. Bármely statikus konstruktor, kezdve az egyes alaposztályokon Object.Object át a közvetlen alaposztályig.
  5. A statikus konstruktor fut. A típus statikus konstruktora fut.

A modul inicializálója alternatívát jelenthet a statikus konstruktorok helyett. További információkért tekintse meg a modul inicializálóinak specifikációját.

Megjegyzések

A statikus konstruktorok a következő tulajdonságokkal rendelkeznek:

  • A statikus konstruktorok nem fogadnak hozzáférési módosítókat vagy paramétereket.
  • Egy osztály vagy szerkezet csak egy statikus konstruktorsal rendelkezhet.
  • A statikus konstruktorok nem örökölhetők vagy túlterhelhetők.
  • A statikus konstruktorokat nem lehet közvetlenül meghívni, és csak a közös nyelvi futtatókörnyezet (CLR) hívhatja meg. A rendszer automatikusan meghívja.
  • A felhasználó nem szabályozhatja, hogy a statikus konstruktor mikor lesz végrehajtva a programban.
  • A rendszer automatikusan meghív egy statikus konstruktort. Inicializálja az osztályt az első példány létrehozása előtt, vagy az adott osztályban deklarált statikus tagokra (nem az alaposztályokra) hivatkozik. Egy statikus konstruktor egy példánykonstruktor előtt fut. Ha a statikus mezőváltozó inicializálói a statikus konstruktor osztályában találhatók, a végrehajtásuk szöveges sorrendben történik, amelyben megjelennek az osztálydeklarációban. Az inicializálók közvetlenül a statikus konstruktor végrehajtása előtt futnak.
  • Ha nem biztosít statikus konstruktort a statikus mezők inicializálásához, a rendszer az összes statikus mezőt az alapértelmezett értékre inicializálja a C# típusú alapértelmezett értékekben felsoroltak szerint.
  • Ha egy statikus konstruktor kivételt jelez, a futtatókörnyezet nem hívja meg másodszor, és a típus nem lesz inicializálva az alkalmazástartomány teljes élettartama alatt. A leggyakrabban akkor jelentkezik kivétel, TypeInitializationException ha egy statikus konstruktor nem tud példányosítani egy típust vagy egy statikus konstruktoron belül előforduló kezeletlen kivételt. A forráskódban explicit módon nem definiált statikus konstruktorok esetében a hibaelhárításhoz szükség lehet a köztes nyelv (IL) kódjának vizsgálatára.
  • A statikus konstruktor jelenléte megakadályozza a típusattribútum hozzáadását BeforeFieldInit . Ez korlátozza a futtatókörnyezet optimalizálását.
  • A deklarált static readonly mező csak a deklaráció részeként vagy statikus konstruktorban rendelhető hozzá. Ha nincs szükség explicit statikus konstruktorra, inicializálja a statikus mezőket deklaráláskor, és ne statikus konstruktoron keresztül a futásidő jobb optimalizálása érdekében.
  • A futtatókörnyezet egyetlen alkalmazástartományban legfeljebb egyszer hív meg statikus konstruktort. A hívás egy zárolt régióban történik az osztály adott típusától függően. A statikus konstruktor törzsében nincs szükség további zárolási mechanizmusokra. A holtpontok kockázatának elkerülése érdekében ne blokkolja az aktuális szálat statikus konstruktorokban és inicializálókban. Ne várjon például tevékenységekre, szálakra, várakozási fogópontokra vagy eseményekre, ne szerezzen be zárolásokat, és ne végezzen blokkoló párhuzamos műveleteket, Parallel.Invoke például párhuzamos hurkokat és párhuzamos LINQ-lekérdezéseket.

Feljegyzés

Bár közvetlenül nem érhető el, az inicializálási kivételek hibaelhárításához dokumentálni kell egy explicit statikus konstruktor jelenlétét.

Használat

  • A statikus konstruktorok általában akkor használatosak, ha az osztály naplófájlt használ, a konstruktor pedig a fájl bejegyzéseinek írására szolgál.
  • A statikus konstruktorok akkor is hasznosak, ha burkolóosztályokat hoznak létre nem felügyelt kódhoz, amikor a konstruktor meghívhatja a metódust LoadLibrary .
  • A statikus konstruktorok a típusparaméter futásidejű ellenőrzésének kényszerítésére is alkalmasak, amelyek fordításkor nem ellenőrizhetők típusparaméter-megkötésekkel.

Példa

Ebben a példában az osztálynak Bus statikus konstruktora van. Az első példány Bus létrehozásakor (bus1) a statikus konstruktor meghívása történik az osztály inicializálásához. A mintakimenet ellenőrzi, hogy a statikus konstruktor csak egyszer fut-e, annak ellenére, hogy két példány Bus jön létre, és hogy a példánykonstruktor futtatása előtt fut.

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 {0}",
            globalStartTime.ToLongTimeString());
    }

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

    // 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("{0} is starting its route {1:N2} minutes after global start time {2}.",
                                this.RouteNumber,
                                elapsedTime.Milliseconds,
                                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# nyelvspecifikáció

További információ: A C# nyelv specifikációjának Statikus konstruktorok szakasza.

Lásd még