2010-09-03 23 views
4

J'ai une classe simple qui a un constructeur statique et un constructeur d'instance. Maintenant, lorsque j'ai initialisé la classe, le constructeur statique et le constructeur d'instance sont appelés. Seul le static est référencé une fois dans un domaine d'application. Puis-je à nouveau appeler la même initialisation de classe et le constructeur statique initialiser à nouveau? J'ai essayé mais ça ne s'est pas passé? Est-il possible de rappeler le constructeur statique dans la méthode main() après avoir utilisé garbage collection sur la classe.Collecteur d'ordures statique C#?

Voici le code:

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

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

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

Maintenant, dans le principal appel de méthode:

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

Sortie:

constructeur statique constructeur appelé Instance appelée constructeur Instance appelée

Maintenant, le statique n'a pas appelé à nouveau. Parce qu'il est appelé une fois dans le domaine d'application. Mais est leur de toute façon nous pourrions l'appeler à nouveau sans décharger le domaine d'application. Pouvons-nous utiliser la classe GC ici?

Merci. Pal

+2

Pourquoi avez-vous écrit ce code sur Terre? –

+1

@Developer: Parce qu'il peut :-D – abatishchev

+0

@Developer ARt, S'il vous plaît alors me dire pourquoi nous ne pouvons pas avoir plusieurs constructeurs statiques dans une seule classe? Pourquoi :-D ...? –

Répondre

8

Sauf si vous le produisez avec une réflexion, le constructeur statique (ou plus généralement, l'initialiseur de type) n'est exécuté qu'une seule fois par classe concrète, par AppDomain.

Notez que pour les génériques, en utilisant différents arguments de type que vous obtiendrez différentes classes concrètes:

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 
2

Pas possible. Le CLR conserve un bit d'état interne qui indique si l'initialiseur de type a été démarré. Il ne peut pas fonctionner à nouveau. Ce bit d'état est en effet stocké dans le tas du chargeur dans le cadre de l'état AppDomain. La solution de contournement est simple, ajoutez simplement une méthode statique à la classe.

1

Le point d'un constructeur est de mettre les choses dans un état valide initial souhaité.

Un constructeur d'instance place une instance dans un état valide initial.

Un constructeur d'instance qui prend des arguments place une instance dans un état valide initial qui reflète ses arguments.

Un constructeur statique met le type dans un état valide initial. Par exemple. initialisation des membres statiques utilisés par les méthodes statiques de la classe ou partagés par toutes les instances.

Idéalement, toutes les méthodes laisseront l'objet et le type dans un état valide, mais les constructeurs diffèrent en étant responsables de l'obtenir en premier lieu. Toute tentative d'appel d'un constructeur à deux reprises est donc une erreur, car "le remettre dans un état valide initial" n'est pas quelque chose que vous pouvez logiquement faire deux fois ("initial" et "again" ne fonctionnent pas bien dans la même clause). Nous sommes aidés par le compilateur (en refusant de compiler) et le langage (puisqu'il n'y a aucun moyen d'exprimer cela) de faire une telle chose. Et, étant une impossibilité logique, ce n'est pas quelque chose que vous pouvez vraiment vouloir faire (enfin, je peux dessiner un triangle avec plus de 3 côtés, mais seulement pour dire que je l'ai fait).Cela suggère que vous utilisez votre constructeur pour faire autre chose que de configurer un état valide initial. Faire quoi que ce soit d'autre que d'établir un tel état valide dans un constructeur est (au mieux) au mieux une optimisation, souvent un défaut de conception sérieux et très probablement (pire de tout parce qu'il se décolle plus longtemps) un tentative d'optimisation qui est vraiment un défaut de conception grave. Un signe que votre tentative d'optimisation est vraiment une faille de conception est un désir d'appeler un constructeur statique plus d'une fois, ou d'appeler un constructeur d'instance plus d'une fois sur le même objet.

Identifiez le comportement répétable souhaité, déplacez-le dans une méthode distincte et appelez-le au besoin depuis le constructeur et ailleurs. Ensuite, vérifiez la logique de votre conception, car c'est une erreur assez grave à trouver dans une conception de classe et suggère que vous avez des problèmes plus profonds.