4 Stimmen

Statischer C# Garbage Collector?

Ich habe eine einfache Klasse, die einen statischen Konstruktor und einen Instanzkonstruktor hat. Wenn ich nun die Klasse initialisiere, werden sowohl der statische als auch der Instanzkonstruktor aufgerufen. Nur der statische Konstruktor wird einmal in einer Anwendungsdomäne aufgerufen. Kann ich dieselbe Klasseninitialisierung erneut aufrufen und den statischen Konstruktor erneut initialisieren? Ich habe es versucht, aber es ist nicht passiert? Gibt es eine Möglichkeit, den statischen Konstruktor in der main()-Methode erneut aufzurufen, nachdem die Garbage Collection für die Klasse verwendet wurde?

Hier ist der Code:

public class Employee
{
    public Employee()
    {
        Console.WriteLine("Instance constructor called");   
    }

    static Employee()
    {
        Console.WriteLine("Static constructor called");   
    }

    ~Employee()
     {
        //Dispose();
     }
}

Jetzt in der Hauptmethode aufrufen:

static void Main(string[] args)
{
    Employee emp = new Employee();
    Employee emp = new Employee();
}

Ausgabe:

Statischer Konstruktor genannt Instanz-Konstruktor genannt Instanz-Konstruktor genannt

Jetzt hat sich das Rauschen nicht mehr gemeldet. Weil es einmal in der Anwendungsdomäne aufgerufen wird. Aber gibt es eine Möglichkeit, wie wir sie erneut aufrufen können, ohne die Anwendungsdomäne zu entladen. Können wir die GC-Klasse hier verwenden?

Danke! Pal

8voto

Jon Skeet Punkte 1325502

Der statische Konstruktor (oder allgemeiner der Typinitialisierer) wird nur einmal pro konkreter Klasse und pro AppDomain ausgeführt, es sei denn, Sie haben ihn mit Reflection überlistet.

Beachten Sie, dass Sie bei Generika mit unterschiedlichen Typargumenten unterschiedliche konkrete Klassen erhalten:

public class Foo<T>
{
    Foo()
    {
        Console.WriteLine("T={0}", typeof(T));
    }
    public static void DummyMethod() {}
}
...
Foo<int>.DummyMethod(); // Executes static constructor first
Foo<string>.DummyMethod(); // Executes static constructor first
Foo<string>.DummyMethod(); // Type is already initialized; no more output

2voto

Hans Passant Punkte 894572

Nicht möglich. Die CLR behält ein internes Statusbit, das verfolgt, ob der Typinitialisierer gestartet wurde. Er kann nicht erneut ausgeführt werden. Dieses Statusbit wird tatsächlich im Heap des Loaders als Teil des AppDomain-Status gespeichert. Die Abhilfe ist einfach, fügen Sie einfach eine statische Methode zur Klasse hinzu.

1voto

Jon Hanna Punkte 106367

Der Sinn eines Konstruktors ist es, die Dinge in einen gewünschten gültigen Anfangszustand zu versetzen.

Ein Instanzkonstruktor versetzt eine Instanz in einen gültigen Anfangszustand.

Ein Instanzkonstruktor, der Argumente entgegennimmt, versetzt eine Instanz in einen gültigen Anfangszustand, der ihre Argumente widerspiegelt.

Ein statischer Konstruktor versetzt den Typ in einen gültigen Anfangszustand. Z.B. Initialisierung von statischen Elementen, die von den statischen Methoden der Klasse verwendet werden oder von allen Instanzen gemeinsam genutzt werden.

Im Idealfall hinterlassen alle Methoden das Objekt und den Typ in einem gültigen Zustand, aber Konstruktoren unterscheiden sich darin, dass sie dafür verantwortlich sind, das Objekt überhaupt erst in einen solchen Zustand zu versetzen.

Jeder Versuch, einen Konstruktor zweimal aufzurufen, ist daher ein Fehler, denn "wieder in einen gültigen Ausgangszustand versetzen" ist etwas, das man logischerweise nicht zweimal tun kann ("initial" und "wieder" funktionieren nicht gut in derselben Klausel). Der Compiler (er weigert sich zu kompilieren) und die Sprache (es gibt keine Möglichkeit, dies auszudrücken) halten uns davon ab, so etwas zu tun.

Und da es sich um eine logische Unmöglichkeit handelt, ist es nichts, was man tatsächlich tun möchte (gut, ich kann ein Dreieck mit mehr als 3 Seiten zeichnen wollen, aber nur um zu sagen, dass ich es getan habe). Dies deutet darauf hin, dass Sie Ihren Konstruktor verwenden, um etwas anderes zu tun, als einen gültigen Anfangszustand zu erzeugen.

Alles andere als die Festlegung eines solchen gültigen Zustands in einem Konstruktor ist (ebenso wie das Unterlassen) bestenfalls eine Optimierung, häufig ein schwerwiegender Konstruktionsfehler und möglicherweise (was noch schlimmer ist, weil es länger unbehoben bleibt) ein Optimierungsversuch, der in Wirklichkeit ein schwerwiegender Konstruktionsfehler ist.

Ein Zeichen dafür, dass Ihr Optimierungsversuch in Wirklichkeit ein Designfehler ist, ist der Wunsch, einen statischen Konstruktor mehr als einmal aufzurufen oder einen Instanzkonstruktor mehr als einmal für dasselbe Objekt aufzurufen.

Identifizieren Sie das gewünschte wiederholbare Verhalten, verschieben Sie es in eine separate Methode, und lassen Sie sie bei Bedarf sowohl vom Konstruktor als auch von anderen Stellen aus aufrufen. Überprüfen Sie dann noch einmal die Logik Ihres Entwurfs, da dies ein schwerwiegender Fehler in einem Klassendesign ist und darauf hindeutet, dass Sie tiefere Probleme haben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X